• 纠错《COM技术内幕》之ProgID


    最近在看《COM技术内幕》,看到第六章时发现该章节在解释ProgID时有点错误,特此记录一下,也给正在学习COM的小伙伴们一个提示。

    而且我发现该问题存在于一些很多大型软件的COM组件中。(开发者估计都是看了该书吧)

    在该书的6.3.5章节讲解了ProgID的在注册表中的格式,示例如下

    注册表文件格式为

    Windows Registry Editor Version 5.00
    
    [HKEY_CLASSES_ROOTAA.BBCLSID]
    @="{00000000-F2ED-4CD4-9204-A1C28871DD2E}"
    
    [HKEY_CLASSES_ROOTAA.BBCurVer]
    @="AA.BB.1"
    
    [HKEY_CLASSES_ROOTAA.BB.1CLSID]
    @="{00000000-F2ED-4CD4-9204-A1C28871DD2E}"

    (上面我故意将CLSID的第一节写为零了,仅仅只是为了读者容易区分后面的其他CLSID)

    书中也讲到了,这么做的目的是为了客户在使用COM组件时可以通过“AA.BB”这个与版本无关的ProgID来映射到最新版本的组件

    在上例中也就是“AA.BB.1”这个版本。引用书中的一段原话“与版本号无关的ProgID关键字Helicopter.TailRotor包含两个关键字CLSID及CurVer。”

    也就是上面注册表文件中所描述的格式。为了验证书中所说的,我们把"AA.BB.1”的CLSID改一下

    Windows Registry Editor Version 5.00
    
    [HKEY_CLASSES_ROOTAA.BBCLSID]
    @="{00000000-F2ED-4CD4-9204-A1C28871DD2E}"
    
    [HKEY_CLASSES_ROOTAA.BBCurVer]
    @="AA.BB.1"
    
    [HKEY_CLASSES_ROOTAA.BB.1CLSID]
    @="{11111111-F2ED-4CD4-9204-A1C28871DD2E}"

    那么是不是真的可以通过“AA.BB”映射到“AA.BB.1”呢?编写如下测试代码

    #include "stdafx.h"
    #include <iostream>
    #include <Windows.h>
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        CLSID clsid;
        CLSIDFromProgID(L"AA.BB", &clsid);
        LPOLESTR str;
        StringFromCLSID(clsid, &str);
        std::wcout << str << std::endl;
        CoTaskMemFree(str);
    
        system("pause");
        return 0;
    }

    运行结果如图

    很可惜,取到的CLSID还是“AA.BB”的,并非“AA.BB.1”的CLSID。

    看到这里你也许会发现,在我们的系统中,有着这个问题的COM组件有很多,比如迅雷的

    腾讯的

    它们都无法从“与版本号无关的ProgID”映射到“具体版本的ProgID”。

    一般来说升级COM组件的最佳方式还是升级内部接口的方式,如IX2、IX3等,并不会选择去添加一个新的COM组件的方式。

    所以这个问题也不算是个问题。

    回到正题,那么如何做才是正确的呢?其实很简单,只要把“AA.BB"的CLSID键删除即可

    Windows Registry Editor Version 5.00
    
    [-HKEY_CLASSES_ROOTAA.BBCLSID]
    
    [HKEY_CLASSES_ROOTAA.BBCurVer]
    @="AA.BB.1"
    
    [HKEY_CLASSES_ROOTAA.BB.1CLSID]
    @="{11111111-F2ED-4CD4-9204-A1C28871DD2E}"

    这样,CLSIDFromProgID才会真正的工作正常,再次运行测试程序得到”AA.BB.1“的CLSID

    CLSIDFromProgID会查找用户指定的ProgID,如果其下有子键”CLSID“的话,则认为该ProgID是一个具体版本的。

    否则该ProgID只是起到映射的作用,它实际会跳到”CurVer“键所指向的ProgID。

    《COM技术内幕》中所讲到的与版本无关的ProgID都添加了CLSID键,这样会导致该ProgID不是一个能映射的ProgID。

    转载地址:http://blog.csdn.net/aqtata/article/details/36915823

    作者:牛弟弟
    出处:http://www.cnblogs.com/dj-smile/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    ES6学习笔记(七)-对象扩展
    ES6学习笔记(四)-数值扩展
    ES6学习笔记(三)-正则扩展
    ES6学习笔记(二)-字符串的扩展
    ES6学习笔记(一)-变量的解构赋值
    webpack打包踩坑之TypeError: Cannot read property 'bindings' of null
    CSS之Flex 布局
    iscsi
    DHCP
    DNS
  • 原文地址:https://www.cnblogs.com/dj-smile/p/7784428.html
Copyright © 2020-2023  润新知