【发布时间】:2015-08-26 11:40:35
【问题描述】:
我有一个进程内 COM 服务器,我想为其构建 32 位和 64 位版本。我可以毫无问题地做到这一点。但是,我在注册两个版本时遇到了一些问题。
我没有使用 ATL。在我的 DllRegisterServer 函数中,我使用的是RegisterTypeLibForUser。我通过使用我的 DLL 路径调用 LoadTypeLibEx 来获取 RegisterTypeLibForUser 调用的 ITypeLib 实例,并且我正在使用 REGKIND_NONE 标志。我正在使用 .idl 和 MIDL 编译器创建我的类型库。我将类型库作为资源嵌入到我的 .dll 中。鉴于下面的前两个项目符号(一切都按预期工作),我这样做的方式似乎没有任何问题。
- 如果我只注册 32 位,则在 32 位客户端中一切正常,而在 64 位客户端中会出现预期故障(未注册类)。
- 如果我只注册 64 位,则在 64 位客户端中一切正常,而在 32 位客户端中会出现预期故障(未注册类)。
- 如果我先注册 64 位,然后注册 32 位,则在 32 位客户端中一切正常,但在 64 位客户端中出现故障。如果我随后取消注册 32 位服务器,则 64 位客户端继续失败。如果我重新注册 64 位服务器(无论是否取消注册),64 位客户端都可以工作。
- 如果我先注册 32 位,然后注册 64 位,则在 64 位客户端中一切正常,但在 32 位客户端中出现故障。如果我随后取消注册 64 位服务器,则 32 位客户端继续失败。如果我重新注册 32 位服务器(无论是否取消注册),32 位客户端都可以工作。
看来,当我注册两台服务器时,后一个 RegisterTypeLibForUser 调用会破坏前一个 RegisterTypeLibForUser 调用的注册表设置。
至于我遇到的错误:
- 只要注册了正确的服务器,CoCreateInstance 就始终有效。在 32 位客户端中,只要注册了 32 位服务器,CoCreateInstance 就可以工作(即使也注册了 64 位服务器)。带有 64 位服务器的 64 位客户端也是如此。
- 在CoCreateInstance 工作的任何情况下,我都可以调用对象上的方法。我可以在公寓之间编组我的接口(我正在使用全局接口表),并且我可以在编组的接口上调用方法。
- 我得到的错误与ICallFactory 在一个已编组接口的公寓中特别相关。我可以在编组接口上查询ICallFactory,没有任何问题。但是,当我使用异步接口的 IID 调用 CreateCall 时,收到错误 E_NOINTERFACE。
- 如上一个列表中所述,只要上次注册的服务器是与客户端具有相同目标平台的服务器,我就不会收到此错误。
我现在正试图深入研究我的注册表,并确切地弄清楚注册发生时发生了什么变化,但是由于注册表重定向器,这并不是那么简单。当我发现注册表信息时,我会更新这篇文章。
【问题讨论】:
-
尝试使用SysInternals Process Monitor 来查看
RegisterTypeLibForUser()对注册表的实际作用。听起来注册是在某处修改共享密钥,而不是使用单独的 32/64 位密钥。 -
找到了。它与 RegisterTypeLib/RegisterTypeLib 的使用方式有关,为接口编写 ProxyStubClsid32 键。
标签: windows winapi com registry typelib