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

64-bit managed process: out-of-proc 32-bit COM server non-default interfaces not available

我正在将最初用 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<类型库 GUID><类型库版本>

  • HKCR\TypeLib<类型库 GUID><类型库版本>\0

  • HKCR\TypeLib<类型库 GUID><类型库版本>[=64=]\win32 = “类型库文件路径”

  • HKCR\TypeLib<类型库 GUID><类型库版本>\Flags

  • HKCR\TypeLib<类型库 GUID><类型库版本>\HelpDir = “帮助文件夹路径”

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

  • [HKEY_CLASSES_ROOT\Interface<接口 GUID>\ProxyStubClsid32 ="{00020424-0000-0000-C000-000000000046}"

  • HKCR\Interface<接口GUID\TypeLib = 类型库 GUID

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

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

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

所有这些都在“COM 和 ATL 3.0 开发人员研讨会”的第 5 章中有详细说明。