进程外COM服务器的注册表项

时间:2012-10-19 17:36:55

标签: com out-of-process

我正在实施我的第一个进程外COM服务器(我的第一个COM服务器,就此而言)。我已按照步骤编写IDL文件,生成代理/存根DLL的代码,编译DLL并注册它。

当我检查注册表项时,我有

  • 名为HKEY_CLASSES_ROOT/Interface/<GUID>的密钥,其值为(例如)IMyApp
  • 名为HKEY_CLASSES_ROOT/Interface/<GUID>/ProxyStubClsid32的密钥,其值为<GUID>,即与密钥名称相同的值

我不明白第二个键的值如何与键名中的<GUID>值相同,因为我目前的理解是

  • HKEY_CLASSES_ROOT/Interface/<GUID>中,GUID是界面 ID
  • ProxyStubClsid32不是接口ID,而是指向实现上述接口的组件的 ID
  • HKEY_CLASSES_ROOT/CLSID/<GUID>/InprocServer32(其中GUID是上述 ID)的值指向代理DLL

如果一个是接口ID而另一个是类ID,HKEY_CLASSES_ROOT/Interface/<GUID>/ProxyStubClsid32的值如何保持相同的值GUID?

编辑:我仍然希望得到这个问题的答案。简而言之:由于组件和接口是两个不同的东西,如何同时使用相同的ID?

3 个答案:

答案 0 :(得分:6)

您对COM中使用Guids的方式的基本理解是正确的。值得注意的是,具有相同guid的接口和coclass不是问题。它们存在于不同的注册表项HKCR \ Interface vs HKCR \ CLSID中,无论您是在查找IID还是CLSID,它都会在COM中清晰显示。

其次是你写的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.

您使用Project + Properties,C / C ++,Preprocessor,Preprocessor Definitions设置指定的那个。请注意,您的项目将指定它。

追逐汤然后把你放在这个:

// 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相同。功能,而不是错误。

答案 1 :(得分:0)

初学者混乱(tm)的案例。通过致电regsrv32注册的课程不是我的 CLSID。它是专门为代理/存根DLL生成的(友好名称PSFactory也表示这一点)。因为罗曼R.怀疑,有两个班级,我认为只有一个班级。当我使用/Embedding开关调用时,EXE服务器会注册我自己的CLSID。

答案 2 :(得分:0)

据我所知,MIDL现在管理所有代理/存根混乱(继承自IDispatch而不是IUnknown,您可能已经这样做,因为您拥有ProxyStubClsid32注册表项)。

唯一需要的是正确注册服务器(只是构建它或者/ RegServer没有为我们正确注册它......以及其他许多人),这样做只需要调用LoadTypeLibEx(构建之后)服务器或安装它。)

所以只需使用此代码创建一个小exe,并在构建和安装后调用它:

String^ l_TLB = l_Path + "\\MyServer.tlb";
IntPtr  l_TLBP = System::Runtime::InteropServices::Marshal::StringToBSTR(l_TLB);
ITypeLib *pTypeLib;
HRESULT hr = LoadTypeLibEx(static_cast<LPCOLESTR>(l_TLBP.ToPointer()), REGKIND_REGISTER, &pTypeLib);
if(SUCCEEDED(hr))
    pTypeLib->Release();