在 64 位环境中使用 32 位 COM 对象
本文关键字:COM 对象 环境 | 更新日期: 2023-09-27 17:52:50
下面的代码在 32 位 c# 应用程序中执行没有问题。
object obj = system.Runtime.InteropServices.Marshal.GetActiveObject("Due.Application");
var due = (Due.IDueApplication2)obj;
现在,我尝试让相同的代码在 64 位 c# 应用程序中工作,因此我按照
http://www.gfi.com/blog/32bit-object-64bit-environment/或 http://www.codeproject.com/Tips/267554/Using-bit-COM-Object-from-bit-Application
运行 64 位应用程序时的两种情况
- 到期未运行,第一个代码行失败并显示
HRESULT: 0x800401E3 (MK_E_UNAVAILABLE)
。这很好,在 32 位版本中也会发生。 - Due正在运行,在第一个代码行中
obj
接收一个 COM 对象。但是,第二个代码行抛出InvalidCastException
QueryInterface
因为HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)
失败。(显然,这适用于 32 位版本。
Q 我必须怎么做才能使第二行代码中的演员表成功?
编辑 按照@HansPassant的建议,我启动了ProcessMonitor并监视了32位和64位应用程序。我观察到 64 位应用程序在执行 GetActiveObject
(第 1 行代码(时省略了访问 COM 对象特定的 dll(CreateFile、QueryBasicInformationFile、QueryNameInformationFile 等(,相比之下,32 位应用程序这样做了,即使我事先添加了相应的注册表项,即 AppID
,DllSurrogate
。
编辑1我删除了我添加的所有注册表项,并仔细检查了结果,包括进程监视器的日志文件。我没有注意到任何差异 - 与以前相同的症状。
更新 在第三方软件的目录中,我找到了一个Due.tlb
,并尝试创建一个运行时可调用包装器,如 64 到 32 位互操作中提示的那样 - 如何?
我用tlbimp.exe Due.tlb /out:Interop.due.dll
创建了一个Interop.due.dll
.不幸的是,当我用新创建的与平台无关的 32 位Interop.deu.dll
替换时,我的解决方案无法编译(缺少引用(。
唯一有效的是进程外解决方案。我实现了一个 32 位 WCF 服务,该服务提供对 64 位进程的 COM 对象的访问。(因此,我自己实现了代理。
广告更新
好消息
通过利用这篇文章中的信息,我能够重新生成Interop.due.dll
的平台不可知版本。尽管如此,TlbImp.exe
警告我 TI3002 :将类型库导入与平台无关的程序集。 如果类型库不是真正与平台无关的,则这可能会导致错误。
坏消息
没有提供承诺的胶水代码,因此 64 位和 32 位的桥接没有成功。(仅 32 位版本像以前一样工作。