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,等等


相关文章推荐

用 PictureVal 直接在 Image 控件上显示系统默认文件类型的图标

表单上加一个 Image 和 CommandButton 控件,按钮的 Click 中贴下面代码: Local cFile, nSize, cSFI, nBuf, nWidth, nHeight, n...
  • dkfdtf
  • dkfdtf
  • 2014年03月30日 11:37
  • 1238

Windows 下直接控制打印端口

近日在完成最后的 POS 打印模块时有所斩获。POS 机的小票打印是一个不太好控制的内容,原因是小票的长度从来不固定,它要根据用户购买的货品种类,以及附加信息的不同(例如可能需要打印折扣/优惠/会员等...
  • dkfdtf
  • dkfdtf
  • 2008年09月13日 19:55
  • 2624

通过配置manifest实现COM免注册

XP以上的操作系统支持COM免注册技术,操作系统在加载EXE时会自动扫描是否包含配套的manifest信息,若有则读取manifest内容加载组件,否则读取注册表。 manifest描述了EXE里面引...

免注册COM使用参考

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

com技术组件第7章,用vs2005编译示例代码,com注册不成功。

com第7章,编译问题,解决方案

vfp COM 免注册验证示例

  • 2017年02月03日 23:15
  • 23KB
  • 下载

C#免注册COM使用实例

  • 2014年10月20日 16:20
  • 55KB
  • 下载

COM中的HRESULT, CLISD,ProgID, DLL注册,COM库函数的知识(COM技术内幕笔记之三)

http://www.cnblogs.com/shipfi/archive/2007/02/12/648465.html COM中的HRESULT, CLISD,ProgID, DLL注册,COM库...
  • ksrsoft
  • ksrsoft
  • 2012年09月04日 16:22
  • 1061

TC COM插件接入百宝云注册码系统示例

TC COM插件接入百宝云注册码系统示例 接入之前请注意一下,这个免费的系统亲测能跑80个左右的用户。用户太多请安装升级版。TCDLL接入本系统分三步走: 一、首先安装好web网络验证系统,安装完之后...

COM 组件设计与应用(七)——编译、注册、调用

本文摘自:http://www.vckbase.net/index.php/wv/1218 一、前言 上两回中,咱们用 ATL 写了第一个 COM 组件...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:COM 免注册技术
举报原因:
原因补充:

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