进程外COM服务器的注册表项
我正在实现我的第一个进程外COM服务器(就此而言,我的第一个COM服务器)。我按照以下步骤编写了一个IDL文件,为代理/存根DLL生成代码,编译DLL并注册它 当我检查注册表项时,我进程外COM服务器的注册表项,com,out-of-process,Com,Out Of Process,我正在实现我的第一个进程外COM服务器(就此而言,我的第一个COM服务器)。我按照以下步骤编写了一个IDL文件,为代理/存根DLL生成代码,编译DLL并注册它 当我检查注册表项时,我 名为HKEY\u CLASSES\u ROOT/Interface/的键,其值为(比如)IMyApp和 名为HKEY\U CLASSES\U ROOT/Interface//ProxyStubClsid32的键,其值为,即与键名中的值相同 我不明白第二个键的值如何与键名中的值相同,因为我目前的理解是 在HKE
- 名为
的键,其值为(比如)HKEY\u CLASSES\u ROOT/Interface/
和IMyApp
- 名为
的键,其值为HKEY\U CLASSES\U ROOT/Interface//ProxyStubClsid32
,即与键名中的值相同
- 在
中,GUID是一个接口IDHKEY\u CLASSES\u ROOT/Interface/
的值不是接口ID,而是引用实现上述接口的组件的类IDProxyStubClsid32
(其中GUID是上述类ID)的值指向代理DLLHKEY\u CLASSES\u ROOT/CLSID//InprocServer32
HKEY\u CLASSES\u ROOT/Interface//ProxyStubClsid32
的值如何保持相同的值GUID
编辑:我仍然希望得到这个问题的答案。简而言之:既然组件和接口是两件不同的事情,那么如何将相同的ID用于两者呢?您对COM中使用GUID的基本理解是正确的。首先值得注意的是,具有相同guid的接口和类不是问题。它们位于不同的注册表项中,HKCR\Interface与HKCR\CLSID,在COM中,无论您是在查找IID还是CLSID,总是很清楚 第二个是您编写的IDL。注意,这里没有指定代理的CLSID的位置,只有代理和存根支持的IID可以在那里声明 接下来,您需要通过自动生成代理/存根的方式进行白鹅追逐。Windows SDK的核心头文件是RpcProxy.h,请在文本编辑器中打开它查看。宏汤很重,但它确实有一些像样的评论来描述正在发生的事情。重要的RPC帮助程序函数是NdrDllRegisterProxy(),它注册代理并在使用Regsvr32.exe时调用。其第3个参数指定代理的CLSID。我将让您阅读并引用.h文件中的重要部分: 编译器开关:
-DPROXY_CLSID=clsid
Specifies a class ID to be used by the proxy DLL.
您可以使用“项目+属性”、“C/C++”、“预处理器”、“预处理器定义”设置来指定此项。请注意,您的项目不会指定它
在汤中追逐,然后让你进入这一步:
// if the user specified an override for the class id, it is
// PROXY_CLSID at this point
#ifndef PROXY_CLSID
#define GET_DLL_CLSID \
( aProxyFileList[0]->pStubVtblList[0] != 0 ? \
aProxyFileList[0]->pStubVtblList[0]->header.piid : 0)
#else //PROXY_CLSID
#define GET_DLL_CLSID &PROXY_CLSID
#endif //PROXY_CLSID
换句话说,如果您自己没有指定CLSID(您没有),那么它将使用存根表中的第一个IID
这使得ProxyStubClsid32 guid与第一个接口的IID相同。特性,而不是bug。您对COM中使用GUI的基本理解是正确的。首先值得注意的是,具有相同guid的接口和类不是问题。它们位于不同的注册表项中,HKCR\Interface与HKCR\CLSID,在COM中,无论您是在查找IID还是CLSID,总是很清楚 第二个是您编写的IDL。注意,这里没有指定代理的CLSID的位置,只有代理和存根支持的IID可以在那里声明 接下来,您需要通过自动生成代理/存根的方式进行白鹅追逐。Windows SDK的核心头文件是RpcProxy.h,请在文本编辑器中打开它查看。宏汤很重,但它确实有一些像样的评论来描述正在发生的事情。重要的RPC帮助程序函数是NdrDllRegisterProxy(),它注册代理并在使用Regsvr32.exe时调用。其第3个参数指定代理的CLSID。我将让您阅读并引用.h文件中的重要部分: 编译器开关:
-DPROXY_CLSID=clsid
Specifies a class ID to be used by the proxy DLL.
您可以使用“项目+属性”、“C/C++”、“预处理器”、“预处理器定义”设置来指定此项。请注意,您的项目不会指定它
在汤中追逐,然后让你进入这一步:
// if the user specified an override for the class id, it is
// PROXY_CLSID at this point
#ifndef PROXY_CLSID
#define GET_DLL_CLSID \
( aProxyFileList[0]->pStubVtblList[0] != 0 ? \
aProxyFileList[0]->pStubVtblList[0]->header.piid : 0)
#else //PROXY_CLSID
#define GET_DLL_CLSID &PROXY_CLSID
#endif //PROXY_CLSID
换句话说,如果您自己没有指定CLSID(您没有),那么它将使用存根表中的第一个IID
这使得ProxyStubClsid32 guid与第一个接口的IID相同。功能,而不是bug。初学者困惑案例(tm)。通过调用
regsrv32
注册的类不是具有myCLSID的类。它是专门为代理/存根DLL生成的(友好名称PSFactory也表示这一点)。正如罗曼·R.所怀疑的,有两个阶级,我以为只有一个。当使用/Embedding
开关调用我自己的CLSID时,EXE服务器会注册它。初学者困惑案例(tm)。通过调用regsrv32
注册的类不是具有myCLSID的类。它是专门为代理/存根DLL生成的(友好名称PSFactory也表示这一点)。正如罗曼·R.所怀疑的,有两个阶级,我以为只有一个。我自己的CLSID在使用/Embedding
开关调用时由EXE服务器注册。据我所知,所有代理/存根混乱现在都由MIDL管理(继承自IDispatch而非IUnknown,您可能已经这样做了,因为您有ProxyStubClsid32注册表项)
唯一需要做的就是正确注册服务器(只是构建它或doing/RegServer没有为我们以及其他许多人正确注册它),要做到这一点,只需要调用LoadTypeLibEx(在构建服务器或安装它之后)
所以只要用这个c创建一个小的exe