【问题标题】:COM `HRESULT` is wrapped into an Exception in .NETCOM `HRESULT` 被包装到 .NET 中的异常中
【发布时间】:2011-06-16 11:31:46
【问题描述】:

(初步说明:我还没有完全掌握整个“互操作”的东西......)

在 .NET 中使用 COM 库时,所有 HRESULT 方法都被包装到返回码不成功时抛出的东西中。

//ATL magic exluded
class C {
    HRESULT foo(){ return E_FAIL; }
};

// usage code:
if( SUCCEEDED( c.foo() ) ) {
   // success code
} else {
   // failure code
}

此代码的 .NET 对应内容如下:

try {
   c.foo();
   // success code
} catch ( Exception e ) {
   // failure code
}

有没有办法直接在.NET中访问COM返回码,这样就不需要异常处理了?

【问题讨论】:

    标签: .net exception com-interop hresult


    【解决方案1】:

    是的,但您必须手动定义互操作接口(而不是使用 tlbimp.exe)并在相关方法上使用 PreserveSig 属性。

    例如:

    [ComImport]
    [Guid("your-guid-here")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IMyComInterface
    {
         [PreserveSig]
         int DoSomething(out int result);
    }
    

    这相当于带有签名HRESULT DoSomething([out, retval] int *result);的COM方法

    如果你的界面非常复杂或者你在如何定义互操作界面上遇到困难,我推荐使用 tlbimp.exe,然后使用 Reflector 或 ILSpy 或类似的东西来反编译生成的界面,然后根据自己的喜好进行编辑。也节省了工作量。 :)

    【讨论】:

    • 我只是想更清楚地指出[PreserveSig] 是用来表示是否要将 HRESULTS 转换为异常的属性。还应该注意的是,您通常想要使用异常。 HRESULTS 之所以存在,是因为并非所有语言都以相同的方式处理异常,因此它们需要一种不基于异常的机制来报告异常。一旦您使用自己的语言,HRESULT 应该(理想情况下)转换为您的语言的本机异常机制。
    • 这不是您想要使用[PreserveSig] 的唯一原因。有一些 COM 接口无论好坏都使用 HRESULT 作为布尔值;这些函数可以返回 S_OK、S_FALSE 或错误值。如果您不使用[PreserveSig],则无法知道它返回的是 S_OK 还是 S_FALSE。这不仅适用于 S_FALSE,而且适用于任何非错误 HRESULT。幸运的是,这样做的 COM 类很少见,但它们确实存在。
    • 还有一个非常奇怪的IProgressDialog.HasUserCancelled 方法,它甚至不返回HRESULT(与接口的其余方法一样),而是返回BOOL。 (几乎可以肯定,Windows 95 的原始界面中存在错误,现在为了兼容性而被冻结)
    猜你喜欢
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 2011-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多