gpt4 book ai didi

windows - ICallFactory 并排提供 32 位和 64 位类型库

转载 作者:可可西里 更新时间:2023-11-01 14:13:36 25 4
gpt4 key购买 nike

我有一个进程内 COM 服务器,我想为其构建 32 位和 64 位版本。我可以毫无问题地做到这一点。但是,我在注册两个版本时遇到了一些问题。

我没有使用 ATL。在我的 DllRegisterServer 函数中,我使用 RegisterTypeLibForUser .我正在收购 ITypeLib RegisterTypeLibForUser 的实例调用电话LoadTypeLibEx使用我的 DLL 路径,并且我正在使用 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 位客户端中,CoCreateInstance只要 32 位服务器已注册(即使 64 位服务器也已注册),它也能正常工作。 64 位客户端与 64 位服务器同上。
  • 在任何情况下 CoCreateInstance有效,我可以调用对象上的方法。我可以在单元之间编码我的接口(interface)(我正在使用全局接口(interface)表),并且我可以在编码的接口(interface)上调用方法。
  • 我遇到的错误特别与 ICallFactory 有关在接口(interface)已编码到的公寓中。我可以查询 ICallFactory在编码接口(interface)上没有任何问题。但是当我调用 CreateCall使用异步接口(interface)的 IID,我收到错误 E_NOINTERFACE。
  • 如前一列表所述,只要最后注册的服务器是与客户端具有相同目标平台的服务器,我就不会收到此错误。

我现在正试图深入了解我的注册表,并弄清楚在注册过程中到底发生了什么变化,但由于注册表重定向器的存在,这并不是那么简单。我会在发现注册表信息时更新这篇文章。

最佳答案

想通了。

在 64 位操作系统上运行时,RegisterTypeLib 和 RegisterTypeLibForUser 始终写入 32 位和 64 位条目(即使进程是 32 位)。这在大多数情况下是完全可以接受的,因为它只是被写入的接口(interface)和类型库元数据。写入接口(interface) key 时,RegisterTypeLib/RegisterTypeLibForUser 将 ProxyStubClsid32 设置为适用于接口(interface)类型(双重、自动化等)的通用默认 p/s。但是,通用代理/ stub 似乎无法在自定义异步接口(interface)上与 ICallFactory 一起使用。我修改了我的注册例程以始终在 32 位和 64 位注册表项中设置我的自定义代理/ stub 信息。这可确保以后的注册不会取代之前注册的信息。

[更新]:最后,由于可用 APIS 中的几个弱点,我不得不编写自己的注册例程:

  • RegisterTypeLib 和 RegisterTypeLibForUser 不写入 AsynchronousInterface、SynchronousInterface 和 NumMethods 注册表项。这是因为编译类型库中没有显式链接同步和异步接口(interface)的信息。我自己的注册例程按名称匹配接口(interface)——它找到具有相应 AsyncIXxx 接口(interface)的 IXxx 接口(interface)(仅按名称,没有方法比较)并适本地设置这些注册表项。
  • RegisterTypeLib 和 RegisterTypeLibForUser 始终写入 32 位和 64 位注册表项,包括但不限于 ProxyStubClsid32。这意味着通过这种方式注册类型库将覆盖以前通过其他方式编写的相反体系结构的任何 ProxyStubClsid32。要解决这个问题,可以先注册两个类型库(32 和 64),然后再注册代理/ stub dll。然而:
  • MIDL 编译器生成的代理/ stub 代码似乎没有提供任何方式在每个用户注册表中注册 p/s。如果需要按用户注册,则生成的注册例程没有用。
  • 即使生成的代理/ stub 注册例程可以是针对每个用户的,如果代理/ stub 合并到 com 服务器 dll 中,则只有一个注册机会——单个 dll 中的单个 DllRegisterServer。如果该例程仅在注册表的一侧(32 位或 64 位,而不是两者)写入 ProxyStubClsid32 条目,则随后为另一个体系结构注册 dll 将更改第一个体系结构的 ProxyStubClsid32。
  • 我还没有测试过 CoRegisterPSClsid 等一些 API。由于文档没有说明每用户注册,我想它不受支持。

关于windows - ICallFactory 并排提供 32 位和 64 位类型库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30769574/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com