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

时间:2011-06-06 23:42:56

标签: c# com

我目前正在升级到一个广泛使用COM / MFC /(谁知道有多少其他技术)的项目。作为升级的一部分,我们尝试将尽可能多的功能移植到托管C#代码中,但遗憾的是有些东西无法移动(原因我不会进入)。其中一个问题是严重滥用COM的代码段,并返回HRESULT中的指针,这些指针稍后会被转换为各种其他COM接口实现对象。我已经尝试了以下代码将HRESULT转换为指针,然后我可以从中获取接口:

        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以在任何事件上抛出COM异常但是S_OK(0)?

1 个答案:

答案 0 :(得分:5)

两个想法:

  1. 查找并杀死(或严重致残) 谁实施了这个图书馆
  2. 在托管C ++中实现包装器 因为你需要得到 方法调用直接和我的HResult 想不出办法做到这一点 使用互操作。
  3. 修改

    另一种选择是在C#中声明COM接口,使得每个方法的签名返回一个HRESULT并使用[out retval]作为返回值。这将使您获得并检查所有方法调用的HRESULT,而不仅仅是抛出COMException的方法。

    默认情况下,COM interop typeimport“修复”方法签名,以便在管理端删除HRESULT返回,并且interop层抛出E_FAIL等异常,基本上丢弃S_OK,S_FALSE等。

    This article有一些解释,PreserveSig attriubte文档有一些额外的细节。

    这可能需要您手动声明所有COM接口而不是使用tlbimp,但您可以使用tlbimp来保留COM方法的签名。

    这样你就可以完全保留在C#中了,但是你可以选择使用托管C ++,因为它更容易以非标准的方式与COM进行交互。