【问题标题】:COM surrogate for third party component第三方组件的 COM 代理
【发布时间】:2013-08-28 22:29:51
【问题描述】:

我正在编写一个小型 DLL 组件,它需要访问两个第三方组件来组合数据,其中一个是 32 位的,另一个是 64 位的。两者都在 TypeLib 中注册并且与自动化兼容,因此编组应该不是问题。

如果我正确理解了文档,那么除非组件还具有 AppID 和 DllSurrogate 键,否则无法强制加载代理;由于两者都是第三方组件,我有点不愿意修改它们的注册。

有没有办法在理想情况下没有任何额外依赖项的 DLL 组件的代理进程中激活没有 AppID 的组件中的对象,或者谁能向我解释为什么这是一个坏主意?

【问题讨论】:

  • 自定义代理不是也需要服务器组件有一个 AppID,所以 COM 知道在哪个代理中实例化类吗?如果我添加它,这将影响所有客户端,而不仅仅是我宁愿避免的组件(此外,标准代理应该可以正常工作)。
  • Raymond Chen 建议资源管理器以某种方式 CoCreateInstance 未使用 DllSurrogate 键注册的对象,以便在代理中创建它们 - 我会有兴趣怎么做。
  • @SimonRichter,我怀疑 Explorer 只是使用了一个辅助对象,它控制着它的注册,在进程外创建它,并让它创建插件。

标签: com 64-bit ole


【解决方案1】:

是的,您可以在代理中加载(例如)仅 32 位的 DLL,并通过以下方式从 64 位进程访问它。如果有可用的编组器,这将起作用,通常会有一个带有类型库的组件,因为它们通常使用标准编组器。如果对象需要自定义代理/存根,它将无法工作,因为 64 位版本不存在,或者您一开始就不会遇到这个问题。

首先您需要一个 AppID。如果 DLL 已经有 AppID,您应该使用它。您可以通过查看您感兴趣的 CoClass 的 CLSID 键来查找。

这里使用的示例是Capicom.HashedDataCapicom.EncryptedData 类。 Capicom 只有 32 位。

您应该使用 32 位版本的 Regedit 来执行此操作,因为它是 32 位组件。如果您想要从 32 位访问 64 位组件,请使用另一个。 (这是因为 32 位兼容层的注册表虚拟化 - 使用匹配的 regedit 位数版本可以为您解决这个问题,确保您编辑正确的注册表虚拟化版本。

Windows Registry Editor Version 5.00


;;; Capicom AppID - just using the Capicom.EncryptedData CLSID
;;; Use default surrogate = empty string
[HKEY_CLASSES_ROOT\AppID\{A440BD76-CFE1-4D46-AB1F-15F238437A3D}]
"DllSurrogate"=""

;;; Capicom.EncryptedData
[HKEY_CLASSES_ROOT\CLSID\{A440BD76-CFE1-4D46-AB1F-15F238437A3D}]
AppID="{A440BD76-CFE1-4D46-AB1F-15F238437A3D}"

;;; Capicom.HashedData - use same AppID for all!!!!!
[HKEY_CLASSES_ROOT\CLSID\{CE32ABF6-475D-41F6-BF82-D27F03E3D38B}]
AppID="{A440BD76-CFE1-4D46-AB1F-15F238437A3D}"

保存到myComponent-dllhost.reg 文件,然后就可以离开了。

c:\windows\sysWow64\regedit.exe "myComponent-dllhost.reg"

您现在应该能够从 64 位脚本/COM 主机访问 Capicom.HashedData 和 Capicom.EncryptedData。

注意事项:

  • 这仅适用于基本的 OLE 自动化类型。任何与 VBScript 或 JavaScript 中的 Windows Scripting Host 脚本兼容的对象都应该没问题。
  • 您只需将 AppID 添加到可直接创建的对象中。那基本上是那些有 InprocServer32 条目的。从工厂生成的对象或仅作为子对象可用的对象不必添加 AppID。
  • 如果已经有 AppID,您只需添加空字符串“DllSurrogate”条目。就是这样!
  • 这将不会影响 DLL 的正常客户端。只要位数匹配,它们就会像以前一样继续在进程中加载​​。唯一不同的是,它可以从不同位数的客户端在进程外实例化。

【讨论】:

  • 我已经可以使用了,但是我不愿意从我的安装程序中修改其他组件(在本例中为 Lotus Notes 和 Rational ClearCase)的注册,因此我想知道是否有办法在不修改注册表的情况下执行此操作。
  • 别害羞! OTOH,如果你真的想,你可以创建一个相同位数的辅助 com 对象,它只有一个方法HRESULT CreateObject([in] BSTR progID, [out, retval] IUnknown** ppRetVal)。让它在代理中创建对象并将其返回给您。
猜你喜欢
  • 1970-01-01
  • 2010-12-20
  • 2017-01-28
  • 2020-10-28
  • 2017-05-10
  • 2010-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多