64 位托管进程:进程外 32 位 COM 服务器非默认接口不可用

问题描述

我正在将最初用 VB6 编写的 Excel 加载项迁移到托管代码和 64 位 Excel。该加载项通过 COM 代理与一些旧的 32 位 COM DLL 服务器进行互操作,并且遇到了一个问题,即在运行时只有协同类各自认接口中的方法属性可用。尝试调用组件公开的任何其他接口中的方法属性会导致 System.MissingMethodExceptions。

当迁移的加载项与 32 位 Excel 一起使用并且服务器在进程中运行时,非认接口可用。

是否可以采取任何措施使 64 位模式下的加载项可以使用非认接口?

解决方法

解决方案是使用类型库封送处理(也称为通用封送处理),使用系统提供的 oleaut32.dll 中的封送处理引擎。通用封送拆收器可用于任何自定义接口,前提是参数与变体兼容。

要为接口使用通用封送拆收器,接口被标记为oleautomation,如下例接口所示:

[
    object,oleautomation,uuid(23D4EC0B-96DA-4D18-82BD-40E3AA0483FD),version(1.0),dual,helpstring("Description of ICustomInterface1"),pointer_default(unique)
]
interface ICustomInterface1 : IDispatch
{
    // Methods and properties …
}

通用封送处理还需要以下注册表项:

  • HKCR\TypeLib

  • HKCR\TypeLib\0

  • HKCR\TypeLib\0\win32 = “类型库文件的路径”

  • HKCR\TypeLib\Flags

  • HKCR\TypeLib\HelpDir = “帮助文件夹的路径”

  • [HKEY_CLASSES_ROOT\Interface @="接口名称"

  • [HKEY_CLASSES_ROOT\Interface\ProxyStubClsid32 ="{00020424-0000-0000-C000-000000000046}"

  • HKCR\Interface

使用此类型信息,通用封送拆收器在运行时创建代理存根,无需自定义代理存根 DLL。

在我们的例子中,鉴于组件是基于 ATL 的,一旦接口被标记为“oleautomation”并重建组件,就会自动创建注册表条目。对于非 ATL 项目,这可以通过 Win32 API 的 LoadTypeEx()(我没有尝试过)以编程方式完成。

一旦完成,我们基于 ATL 的组件的非默认接口就可以在我们迁移到 VB.NET 的 Excel COM 加载项的进程外使用。

“COM 和 ATL 3.0 开发人员研讨会”第 5 章详细介绍了所有这些。