COM 免注册技术

原创 2017年02月04日 18:23:21

今天实际应用时,又进行了一些测试,发现与以前看到资料中一些不同的表现,见最后的【补充】部分


通常,实例化 COM 组件前(包括采用这一技术的 DLL/ActiveX 控件),都需要先用 regsvr32 注册该组件或控件,从 XP sp2 开始,微软提供了一种采用 manifest(文件清单)的方式来替代,详见最后的 MSDN 参考资料。由于 COM 的注册信息要写入注册表,一方面给 win7 以后没有管理员身份的应用带来了麻烦,另一个人一直存在的问题的就是所谓的DLL Hell,造成同一控件不同版本之间的干扰。MS 推出 .Net 时采用了程序集的方式来避免这个问题,同时也用文件清单的方式给 COM 带来了新的调用方案,由于不需要将类信息写入注册表,COM 文件的放置位置也可以放到 exe 所在文件夹或它的子目录中,自然也就避免了 DLL Hell 的问题。

文件清单是一个 XML 格式的文本文件,其文件名后缀为 manifest(例如:程序名为 a.exe,则这个清单文件名为 a.exe.manifest),创建类实例时,操作系统(实际上是 ole32.dll 的 CoCreateInstance API 函数)会先检查是否存在清单文件,如果存在有效的清单文件,从把从注册表获取 COM 信息的过程就转变成了从清单文件中读取。这个文件有很多作用,例如:指定运行时的操作身份权限,是否使用系统主题,以及这里提到的描述 COM 注册信息,... 等等

如果你用的是 vfp9,当你 build 成 exe 后,用 ResHacker 打开这个 exe 时,你会发现存在一个序号为 24 的资源,其内容为:


(图一)

是不是很像前面提到的 MSDN 文章中的清单文件?如果你用 eXeScope 打开这个 exe。会发现这个 24 号资源,它就是一个名为 manifest 清单的内容:


(图二)

也就是说,vfp9 的 exe 编译时,已经嵌入了一个默认的 manifest

由于 Windows 默认内置的 manifest 优先于外部的 manifest,因此,我们只要写一个添加了 COM 类声明的新 manifest,重新编译后的 exe 就实现了免注册功能。有一点也许很多人还不知道:vfp9 在编译 exe 时,如果发现存在与要编译的 exe 同名的 manifest 文件,就会用它替换掉默认的清单文件。


下面我们就来验证一下:

1. 创建一个测试用 COM

  a. 新建一项目 -> mycomm

  b. 代码 -> 新建,粘贴下面内容并保存为 mycom.prg

Define Class myComFunc as Session olepublic

Function getName()
	Return 'dkfdtf'
EndFunc

EndDefine
  c. 编译成 dll

2. 创建一个测试用 EXE

  a. 新建项目 -> test

  b. 代码 -> 新建,粘贴下面内容并保存为 test.prg

Local oo, cc

Try
	oo = NewObject('mycom.myComFunc')
	cc = oo.getName()
	MessageBox("RegFree COM: value = " + cc)
Catch
	MessageBox('无法创建 COM 对象.')
EndTry
  c. 编译成 exe

3. 运行这个 exe,应该看到这样一个对话框:

(图三)

4. 现在用  Regsvr32 /u mycomm.dll 注销掉这个 COM,应该看到这个:

(图四)

OK,一切都与未使用免注册技术的情况相符。


现在开始实现免注册功能,下面的内容只是介绍如何实现你自己应用程序实现免注册的步骤和方法;只想了解一下的话,只要下载后面的示例包运行就可以了,其中包含了下面的代码。


1. 在项目所在文件夹,新建一个文本文件,用前面提到的 ResHacker 打开 exe,找到 24号资源,将其中的内容复制粘贴到新建的文本文件中,最后重命名为 test.exe.manifest

,然后用 RegFree 工具包 中的 mt 或 regsvr42 提取 mycom.dll 中注册信息,加入其中,全部内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity 
	version="1.0.0.0" 
	type="win32" 
	name="Microsoft.VisualFoxPro" 
	processorArchitecture="x86"
/>

<description>Visual FoxPro</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
	<security>
		<requestedPrivileges>
			<requestedExecutionLevel level="asInvoker" /> 
		</requestedPrivileges>
	</security>
</trustInfo>

<file name="mycom.dll">
<comClass
	progid = "mycom.myComFunc"
	clsid="{B20DF2B2-7810-4D08-8F3A-2B96786AF03E}"
	threadingModel="Apartment" />
<typelib
	tlbid="{31358D79-374B-49BD-AC99-BFE798831194}"
	version="1.0" helpdir="" />
</file>

<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            language="*"
            processorArchitecture="x86"
            publicKeyToken="6595b64144ccf1df"
        />
    </dependentAssembly>
</dependency>
</assembly>

注释:上面内容直接从 test.exe 的 24 号资源复制过来,并加入了 <file> ... </file>  COM 类描述信息部分;为简明起见,这里只加入了必须的类描述元素,另外,如果 mycom.dll 与 test.exe 不在同一文件夹中,需要加上路径部分,可以是相对或绝对路径。增加的那些 GUID 值,你也可以直接在 mydll.vbr 中找到。如果是第三方控件,大部分情况下你没有这个 vbr 文件,所以我提供给你了上面的 RegFree 工具包来从 dll/ocx 中提取这些信息,用法很简单:

用 mt 来提取:mt.exe -tlb:TBL文件名 -dll: DLL/OCX文件名 -out: 输出结果文件名.txt                       没有专门提供TBL文件的话,TBL就用DLL/OCX 文件

用 regsvr42 提取:regsvr42.exe mycom.dll

两个工具都有缺陷,mt 缺少 progid 项目信息,regsvr42 在 Win7 以上即使以管理员权限运行也可能失败,在 xp 下运行没问题


2. 重新编译 test.exe,vfp 会用上面这个清单文件替换默认的 manifest (24 号资源)

3. 运行 test,应该可以再次看到图三的画面。反复用 regsvr32 注册和注销 mycom.dll,结果应该都一样,这说明无论 COM 是否已注册,都可正常使用;更极端一点,你只复制 mycom.dll 和 test.exe 这两个文件到其他有 vfp 运行库的机器上,不用注册,就可以正常运行。


验证示例:RegFree.rar


参考:

关于COM的Reg-Free(免注册)技术简介及实例讲解

Registration-Free Activation of COM Components: A Walkthrough

regsvr42: Generate SxS Manifest Files from Native DLLs for Registration-Free COM


补充:

可以将类描述部分单独放在清单文件中,不一定要写入 exe 24 号资源中,也就是说,不更改 vfp 编译 exe 时默认生成的 24 号资源,另外单独写一个清单文件一起发布,不重复的部分不会相互干扰。与上面的示例包中的 mycom.dll 对应的清单文件 test.exe.manifest 如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<file name="mycom.dll">
<comClass 
progid="mycom.myComFunc" 
clsid="{B20DF2B2-7810-4D08-8F3A-2B96786AF03E}" 
tlbid="{31358D79-374B-49BD-AC99-BFE798831194}" />
</file>
</assembly>

不过要记住,前面说过,vfp 编译时如果发现项目文件夹中存在同名的 manifest 文件,就会用它替换默认的清单。所以,如果要单独发布清单文件(为了便于 COM 版本更新时只更新 dll 而不用更新 exe),就不要把这个文件放在开发机器上项目所在文件夹中。否则,还是像前面描述的那样比较可靠,将类描述信息插入到复制的默认清单文件中,并在更新 COM 时,同时发布更新的 COM 和重新编译的 EXE 文件。


补充2:

找到一个比较完美的提取并自动生成清单文件的工具:

http://www.rdctools.com/Downloads/SetupRDCToolsCOMManifestBuilderPro.exe

完全免费(首次运行时会显示要激活,只要点击获取激活码按钮,会自动连接到官网,显示你的激活码,不需要输入任何信息)

该工具还有其他一些功能:检查/添加数字签名,压缩,检查/注册/注销 COM/OCX/DLL,等等


COM对象创建过程总结(进程外和进程内)

以前研究过DLL的,刚刚研究了一下EXE的情况,现在总结一下:进程内DLL的情况下: 客户调用CoCreateInstance COM调用CoGetClassObject想获得类厂的接口指...
  • ATField
  • ATField
  • 2007年02月08日 23:19
  • 4406

用免注册COM来避免DLL Hell

   用免注册COM来避免DLL Hell           多年以来,大家似乎已习惯了受折磨于管理COM组件的多个版本,谢天谢地,直到微软免注册COM的出现,才总算结束了这种状态。        ...
  • xieqidong
  • xieqidong
  • 2008年05月23日 09:50
  • 2136

Android中插件开发篇之----动态加载Activity(免安装运行程序)

一、前言又到周末了,时间过的很快,今天我们来看一下Android中插件开发篇的最后一篇文章的内容:动态加载Activity(免安装运行程序),在上一篇文章中说道了,如何动态加载资源(应用换肤原理解析)...
  • jiangwei0910410003
  • jiangwei0910410003
  • 2015年08月30日 14:09
  • 38455

COM技术内幕(笔记)

COM——到底是什么?——COM标准的要点介绍,它被设计用来解决什么问题?基本元素的定义——COM术语以及这些术语的含义。使用和处理COM对象——如何创建、使用和销毁COM对象。基本接口——描述IUn...
  • cometwo
  • cometwo
  • 2015年04月25日 16:37
  • 2605

创建免注册(Registration Free)COM

传统的COM程序一直都需要Windows注册表的支持,如果卸载时程序没有把对应的注册表项清理干净, 可能会导致下次安装程序时出错, 同时, 如果多个程序共享一个COM Server, 一旦其中的一个程...
  • Sento
  • Sento
  • 2010年07月22日 09:47
  • 1424

免注册COM的使用方法

COM对象的传统创建方法,会依赖于注册表,所有应用程序都会依赖到同一个版本的COM。如果不同程序依赖的COM版本不同,而这个COM的版本兼容又没有做得很好的时候,就会出现DLL Hell问题。 微软...
  • HarbinZJU
  • HarbinZJU
  • 2012年08月20日 22:36
  • 3719

COM对象创建过程总结(进程外和进程内)

 以前研究过DLL的,刚刚研究了一下EXE的情况,现在总结一下:进程内DLL的情况下: 客户调用CoCreateInstance COM调用CoGetClassObject想获得类厂的接...
  • maliang1225
  • maliang1225
  • 2007年04月16日 16:47
  • 534

COM技术内幕(笔记)

健忘日记 欢迎UI开发交流与合作 duwenjie@gmail.com 博客园首页博问闪存新随笔联系订阅管理 随笔- 144  文章- 0  评论- 63  ...
  • bigwudan
  • bigwudan
  • 2013年03月24日 00:25
  • 1377

免注册COM使用参考

免注册COM在使用时要使用文件清单(manifest文件),文件清单在使用时可分为两种: 1.程序清单: 指明程序包含哪些依赖组件。 C\C++的程序清单信息可在项目属性中编辑,用于自动生成。 C#的...
  • u011623102
  • u011623102
  • 2014年10月20日 16:06
  • 740

进程外组件免注册COM通信的实现

1。需要添加*.exe.manifest文件, Add进工程,Build.  注: manifest中填写的com端exe路径必须是com exe 的真实存放路径(默认在同级目录下),可设置相对路径...
  • wca_daydayup
  • wca_daydayup
  • 2014年11月03日 19:08
  • 1292
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:COM 免注册技术
举报原因:
原因补充:

(最多只允许输入30个字)