用免注册COM来避免DLL Hell

  

用免注册COM 来避免DLL Hell
 
 
         多年以来,大家似乎已习惯了受折磨于管理COM组件的多个版本,谢天谢地,直到微软免注册COM的出现,才总算结束了这种状态。
         也许一直都梦想拥有可重复使用、动态链接的组件,因为它们可平衡代码量及节省内存——重复有人已经做过的东西好比再发明一次车轮,但成千上万的开发者仍使用着他们的本机DLL,且在文件版本及安装上也没有统一系统化的方法,开发者们经常面临要重写他们自己或其他人的DLL,通俗一点来说叫做“炒现饭”或“做无用功”。
 
         也许这种日子即将永远离我们远去了,即便有了 .NET Framework的全局程序集缓存(GAC)、程序集清单、及托管代码组件,但事实上,我们仍在使用VB6的控件、C++活动模板库(ATL)、或ActiveX进行开发,而这种存在互操作的程序仍可能演变为某天某人的DLL Hell。DLL Hell,顾名思义,是对一种状态的通常描述,指当程序从一个DLL中加载或执行代码时,这个有着相同DLL文件名的文件,行为却与开发者预期的有所不同,也就是说,有着两个以上的同名DLL。大多数这种情况发生在安装程序复制并注册了一个较旧版本的DLL,取代了计算机中较新的版本,或是覆盖了一个同名的文件,还有一种较少见的情况,就是新版本的DLL中取消了向后兼容。
         在任一情况中,原本工作正常的程序会突然退出,这是因为老版本的DLL不支持应用程序所要加载的新版本DLL中的函数,或是新版本的DLL去掉了以前版本中所支持的函数。
         但如果客户机上运行的是Windows XP SP2、Windows Server 2003或更新的Windows操作系统,微软引入的免注册COM(Reg-free COM)就能减少或完全消除DLL冲突。本文主要介绍托管.NET代码下的免注册COM,及用XCOPY来部署COM组件。
 
 
         免注册COM 来了
         为生成一个免注册COM的测试程序,先要解压与本文相关的ZIP文件:首先,打开WaveOutComControl解决方案并生成它;接下来,打开在/FlashCards_CSharp 目录中的FlashCards解决方案并重新生成它。这时,你会看到一个警告,没关系,可以安全地忽略它。从FlashCards的Debug目录中,复制FlashCards.exe两次,一次复制到/Reg目录中,一次复制到/RegFree目录中。
         当你在生成解决方案时,Visual Studio会自动注册其中包含的WaveOut.ocx控件,为演示免注册COM,首先需要清除相关的注册表项(模拟成控件未注册的电脑),打开命令提示符,并输入以下命令卸载掉控件:regsvr32 /u WaveOut.ocx。
         在执行完这些步骤之后,在/Reg与/RegFree目录中,会有示例程序“FlashCards”的两个副本。FlashCards是一个C# .NET 2.0的Windows Form(窗体)应用程序,它显示一些西班牙文及对应的英文翻译,它通过一个XPATH查询,从一个名为lesson1.xml的XML文件中读取单词,并随机显示出来;显示出来之后,FlashCards使用WaveOut.ocx ActiveX控件来播放相关单词的 .wav文件,让用户听到单词最地道的发音。WaveOut.ocx是一个使用C++和MFC编写的本机COM控件,示例程序演示了在不需要创建或修改任何注册表项的情况下,如何使用这个控件,换句话来说,你将看到支持免注册COM的Windows,是怎样加载及使用有着相同名字的多个DLL的。
         目录/Reg为标准“旧COM风格”,可执行文件FlashCards.exe依赖于WaveOut.ocx在注册表中注册为一个COM对象;相比之下,目录/RegFree包含了同样的示例程序,但却是免注册的,快速浏览一遍后会发现,/RegFree包含了一个名为FlashCards.exe.Manifest的文件,这将在后面讨论到。
 
         在命令提示符窗口中,定位到/Reg目录,并运行示例程序Flashcards.exe,因为COM依赖性问题,所以会有如图1所示的错误。
 
图1:COM查找异常:这是一个标准的错误信息,其通常会在一个应用程序调用一个未注册的COM组件时产生。
 
 
         想起来了吧,在我们前面卸载掉 .ocx控件之后,即没有运行用于注册组件的相关安装程序,也没有用regsvr32亲自注册控件,因此,本机程序集加载器(Native Assembly Loader)会报告FlashCard程序中所引用的控件没有注册。
         现在,找到/RegFree子目录,并运行FlashCards.exe,这一次,程序运行了,且没有COM错误。当程序运行后,使用工具栏打开lesson1.xml文件,对任一单词,都可以点击“Play Word”按钮来让ActiveX控件播放相关的 .wav文件。
         作者注:在/RegFree目录中使用的ActiveX控件与/Reg目录中的完全一致,只不过是用免注册的方式调用的。
 
 
         生成免注册COM
         用Visual Studio.NET 2005,生成免注册程序轻而易举,然而,在打开FlashCards解决方案之前,却必须要先注册WaveOut.ocx控件。这多少有点讽刺,尽管可以无须注册COM控件来运行一个程序,但在开发免注册程序的电脑上,却必须要先注册COM组件,所以目前来说,免注册COM仅限于运行时。
         回到命令行,定位到示例程序目录,并输入以下命令:
 
   regsvr32 WaveOut.ocx
 
         这行命令注册了组件,因此现在可以把/Reg目录中的FlashCards程序加载到Visual Studio中了。
         从Reg/FlashCards目录中,打开FlashCards解决方案(sln)文件,在解决方案浏览器中,打开引用文件夹,当添加ActiveX控件WaveOut.ocx到程序窗体时(工具箱-右击-选择项目-COM),Visual Studio添加了两个引用到工程中:WaveOutLib及AxWaveOutLib,这两个文件是由Visual Studio调用aximp.exe为ActiveX控件提供一个包装函数,而自动产生的。设置“isolated”标记为“True”,从而允许免注册发布(见图2)。你可以选择其中任一DLL,Visual Studio会自动更新以匹配另一个。
 
图2:设置COM组件隔离:此处的属性设置是为了免注册,而隔离一个存在互操作的COM组件。
 
 
         现在,当你生成(不管是Debug或Release)FlashCards程序时,Visual Studio同时会创建一个名为FlashCards.exe.Manifest 的XML清单文件,它包含了ClassID及控件的类型库信息——即先前存储在注册表中的信息。
 
         以下是清单文件的某一部分:
 
   <file name="WaveOut.ocx" asmv2:size="28160">
       <hash xmlns="urn:schemas-microsoft-com:asm.v2">
         <dsig:Transforms>
           <dsig:Transform Algorithm=
             "urn:schemas-microsoft-com:HashTransforms.Identity" />
         </dsig:Transforms>
         <dsig:DigestMethod
           Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
         <dsig:DigestValue>7CQJz4x0edO3IsPI6RJ+BlX0m2M=
         </dsig:DigestValue>
       </hash>
       <typelib tlbid="{b5ee8904-c4f5-4256-adba-7b4a300155cc}"
           version="1.0"
           helpdir="D:/code/Projects/WaveOut/release/WaveOut.hlp"
           resourceid="0"
           flags="CONTROL,HASDISKIMAGE" />
       <comClass clsid="{4110cc98-f22a-484c-8b96-8dfe76899360}"
           threadingModel="Apartment"
           tlbid="{b5ee8904-c4f5-4256-adba-7b4a300155cc}"
           progid="WAVEOUT.WaveOutCtrl.1"
           description="WaveOut Control" />
   </file>
 
         有了创建后的清单文件,只需简单地复制release目录(可用XCOPY)到任何电脑上,就可以在没有注册表项的情况下使用该控件,现在,发布一个程序简单得就如复制粘贴一般简单了。不过,最后还得提醒一点,组件隔离免注册后,就不能与其他程序共享了,如果需要在其他程序中也使用相同的组件,仍需要在使用的电脑上正确地注册。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值