纠错《COM技术内幕》之ProgID

摘要:
最近在看《COM技术内幕》,看到第六章时发现该章节在解释ProgID时有点错误,特此记录一下,也给正在学习COM的小伙伴们一个提示。引用书中的一段原话“与版本号无关的ProgID关键字Helicopter.TailRotor包含两个关键字CLSID及CurVer。”看到这里你也许会发现,在我们的系统中,有着这个问题的COM组件有很多,比如迅雷的腾讯的它们都无法从“与版本号无关的ProgID”映射到“具体版本的ProgID”。

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

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

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

纠错《COM技术内幕》之ProgID第1张

注册表文件格式为

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;
}

运行结果如图

纠错《COM技术内幕》之ProgID第2张

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

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

纠错《COM技术内幕》之ProgID第3张

腾讯的

纠错《COM技术内幕》之ProgID第4张

它们都无法从“与版本号无关的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}"

纠错《COM技术内幕》之ProgID第5张

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

纠错《COM技术内幕》之ProgID第6张

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

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

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

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

免责声明:文章转载自《纠错《COM技术内幕》之ProgID》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[leetcode]299. Bulls and Cows公牛和母牛C99标准下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

DCOM

DCOM   求助编辑百科名片   DCOM DCOM(分布式组件对象模型,分布式组件对象模式)是一系列微软的概念和程序接口,利用这个接口,客户端程序对象能够请求来自网络中另一台计算机上的服务器程序对象。DCOM基于组件对象模型(COM),COM提供了一套允许同一台计算机上的客户端和服务器之间进行通信的接口(运行在Windows95或者其后的版本...

使用.Net访问Office编程接口

在这篇文章里面,我将向大家介绍如何在.Net中访问Office所公开的编程接口。其实,不管是使用哪种具体的技术来针对Office进行开发(比如VSTO,或者用C#编写一个Office Add-in,或者在一个WinForms程序中调用Office的功能,甚至在一个ASP.NET应用的服务器端启动一个Excel进程),只要是基于.Net平台,这篇文章所描述的...

C# 互操作性入门系列(四):在C# 中调用COM组件

本文转载自:https://www.cnblogs.com/zhili/archive/2013/01/27/COMInterop.html 本专题概要: 引言 如何在C#中调用COM组件——访问Office 互操作对象 在C# 中调用COM组件的实现原理剖析 错误处理 小结 一、引言 COM(Component Object Modele,组件对象模...

进程内COM与进程外COM

1、进程内和进程外Com COM/DCOM 组件可以在DLL 或EXE 文档中实现。 其中在 DLL 中实现的COM/DCOM组件称为 In-Process Server,因为这些组件是加载到使用它们的客户端应用程序执行程序内存之中。因此当应用程序调用COM/DCOM 组件的服务时,就和一般的程序或函数调用一样,非常快速。 在EXE 中实现的COM/DCO...

创建最简单的exe形式COM组件并在MFC程序调用

来新公司学习接手新项目,拿到代码打开解决方案看到里面竟然有40几个工程,有点吃惊。具体看代码也有很多之前没见过的写法,上了几天火。 有件事就没太搞明白,按照文档的说法上层很多软件都要调用IO服务器,但看程序安装目录,IO服务器其实是一个exe程序,按照我之前的印象,能被别的程序调用的也得是动态库、静态库或者服务。实在想不通exe程序怎么作为接口被别的程序调...