c# - 获取一个 COM 对象以在 C# 中对除 S_OK (0) 以外的任何结果抛出异常

标签 c# com

我目前正在对广泛使用 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 异常?

最佳答案

两个想法:

  1. 找到并杀死(或严重致残) 谁实现了这个库
  2. 在托管 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/

相关文章:

.net - 为什么在 VBScript 中使用 `For Each` 迭代 Hashtable 不起作用?

c++ - 为什么控制面板的 PIDL 会有所不同?

c# - WCF 'one way' 通信实际上是 UDP 吗?

c# - 如何将列表归结为最不常见的字符串?

c# - 使用 HtmlAgilityPack 检测图像 src 中的数据 URI

c++ - 如何在 C++ 中维护对 COM 对象的弱引用?

excel - 使用 Excel 的 ExportAsFixedFormat 失败

c++ - C++ Excel COM自动化-Workbook.SaveAs-找不到成员

c# - 表达评价设计题

c# - 如何在不迁移的情况下在 Visual Studio 中打开项目?