我目前正在对广泛使用 COM/MFC/(谁知道还有多少其他技术)的项目进行升级。作为升级的一部分,我们正尝试将尽可能多的功能移动到托管 C# 代码中,但不幸的是,有些东西无法移动(出于我不会讨论的原因)。其中之一是一段严重滥用 COM 的代码,并在 HRESULT 中返回指针,这些指针随后被强制转换为各种其他 COM 接口(interface)实现对象。我已尝试使用以下代码将 HRESULT 转换为指针,然后我可以从中获取接口(interface):
MyComInterfaceInCS myObj = null;
try
{
world.GetTD_MyComInterfaceInCS();
}
catch (COMException comException)
{
int pointerValue = Marshal.GetHRForException(comException);
IntPtr myObjPointer = new IntPtr(pointerValue);
myObj = (MyComInterfaceInCS) Marshal.GetObjectForIUnknown(myObjPointer);
}
.... 但是,没有抛出 COM 异常,我猜这是因为指针不是负值,因此在技术上不是 COM 错误。有什么方法可以在对象上配置 COM 以在 S_OK (0) 以外的任何内容上抛出 COM 异常?
最佳答案
两个想法:
- 找到并杀死(或严重致残) 谁实现了这个库
- 在托管 C++ 中实现包装器 因为你需要到达 方法调用的 HResult 直接和我 想不出办法 使用互操作。
编辑
另一种选择是在 C# 中声明 COM 接口(interface),这样每个方法的签名都会返回一个 HRESULT 并使用 [out retval] 作为返回值。这将允许您获取并检查所有方法调用的 HRESULT,而不仅仅是那些抛出 COMException 的方法调用。
默认情况下,COM 互操作类型导入“修复”方法签名,以便在托管端删除 HRESULT 返回,并且互操作层抛出 E_FAIL 等异常,实质上丢弃 S_OK、S_FALSE 等。
This article有一些解释和PreserveSig属性文档有一些额外的细节。
这可能需要您手动声明所有 COM 接口(interface),而不是使用 tlbimp但您可以使用 tlbimp 来保留 COM 方法的签名。
这将允许您完全使用 C#,但在您看来,我会选择托管 C++,因为从那里以这种非标准方式更容易与 COM 交互。
关于c# - 获取一个 COM 对象以在 C# 中对除 S_OK (0) 以外的任何结果抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6259253/