免注册COM组件的制作

昨天写的博文说了关于自制COM组件的。一个COM类需要能够被调用,要在注册表的HKEY_CLASS_ROOT里面改啊改。改注册表这事情很烦躁,而且如果要发布什么小工具,“小”工具而已,要在注册表里面改啊改,是非常令人不快的事情。无意间在网上找到说从Windows XP开始,利用SideBySide技术可以让一个COM组件类不需要在注册表里面注册也能够被使用。看着让人十分兴奋,因为这下就可以不需要在注册表里面搞七搞八也可以使用COM组件了。

文章在 http://msdn.microsoft.com/en-us/library/ms973913.aspx#rfacomwalk_topic6 找到的。不过里面没有说到关于progid的设置。progid的设置可以在 http://www.mazecomputer.com/sxs/help/inside2.htm 参考,最后结合起来,成功让一个没有在注册表里面注册的COM类实例化了。

过程中遇到了很烦人的事情,不知道是不是因为windows会把manifest文件缓存起来?因为有的时候发现明明文件改了,但是运行程序结果和原来一样,十分像是缓存没有更新的情况,然后也,也十分像是我哪里忘记改了的情况…………(死目

制作com的方法和以前无异,要搞免注册,最重要的步骤就是嵌入一个manifest文件进dll。这个文件其实是一个xml,比如我昨天搞的那个dll,可以写一个这样的manifest文件:

<?xml version="1.0" encoding="UTF-8"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity type="win32" name="GetHash" version="1.0.0.0" />
    <file name = "GetHash.dll">
        <comClass progid="MyGetHashLib.GetHash" clsid="{E541F90D-16E1-43D0-B115-23AAAE0573DB}" />
        <typelib tlbid="{AB18183F-A79B-49E7-92E8-514A056B2FCB}" version="1.0" helpdir="" />
    </file>
</assembly>

assemblyIdentity里的那个name就是dll的名字,到时候在exe的manifest里面也要引用到,随便写一个不妥的样子。网上有说这个Name如果正好和DLL的名字一样,然后manifest文件又不是嵌入DLL里、文件名又和DLL一样的时候,某些版本的Windows下回出现问题。这也是为什么MSDN上那个文章里的例子里,这里后面加了.X的缘故。嵌入的话,似乎是没问题的……注意看最下面的说明。progid就是类的名字,vb中用CreateObject创建对象的时候可以用这个名字的,而不是uuid。

和教学中相比,有一个什么stub我没看懂的被我删掉了(汗)不过因为删掉以后似乎也可以运行,于是就没去管它了……(殴

然后这个文件作为RT_MANIFEST类型的资源加入到dll中。因为我之前已经弄了一个tlb进dll了,资源编号还是1……尝试把RT_MANIFEST类型的这个资源编号设置到2,也可以运行的样子。

这样这个dll就做了免注册了。但是exe要调用,exe那边也要做一点手脚,光是dll不够。

exe那边也是做一个manifest文件,大概长这样:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity type="win32" name="client" version="1.0.0.0" />
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="GetHash" version="1.0.0.0" />
        </dependentAssembly>
    </dependency>
</assembly>

注意里面那个name="GetHash"部分,这个就是dll的名字。

然后保存成 xxx.exe.manifest这样的名字,xxx是你exe的文件名。因为我测试用的是VB,但是我又不会VB,于是不知道如何把这个manifest嵌入到exe中。不过用C++写的时候,测试的时候把manifest嵌入进去,可行。

于是说到底就是考两个功夫,一个是写manifest,一个是嵌入资源。

另:dll的manifest文件其实也可以单独拿出来,但是在windows xp下,它寻找的时候会先寻找dll,找到了就挖里面的资源,没发现manifest资源的时候……它就不找了!而不是会继续看你外面放的那个单独的manifest文件里面的东西。根据教学,2003下似乎会继续找。不过鉴于这个问题,最方便的方法还是直接嵌入文件里面啦,免得多事,而且一大堆文件又不好看(……

这是试验的代码,VB6的那个要在工程里面引用dll文件才能通过编译。

com_registration_free

补充一下调试的时候可能需要的:

在控制面板——性能和维护——管理工具的“事件查看器”里面,“应用程序”那边来源是SideBySide的错误,如果manifest文件写错了这里面很可能有需要的东西。

再就是mt.exe这玩意儿,通过 mt -manifest xxx.manifest -validate_manifest 可以验证manifest文件有没有写错

发表评论