2011-06-16 22 views
5

(初步說明:我還沒有完全掌握整個'interop'的事情......)COM`HRESULT`被封裝成一個Exception in .NET

當從內部使用COM庫.NET中,所有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返回代碼的方式,這樣就不需要異常處理?

回答

4

是的,但是您必須手動定義互操作界面(而不是使用tlbimp.exe)並在相關方法中使用PreserveSig屬性。

例如:

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

這是一個COM方法與簽名HRESULT DoSomething([out, retval] int *result);

如果你的界面很複雜或您遇到問題如何定義互操作界面,我推薦的等效使用tlbimp.exe,然後使用Reflector或ILSpy或類似的東西來反編譯生成的接口,然後根據自己的喜好編輯這些接口。也節省工作。 :)

+0

我只想更清楚地指出''[PreserveSig]'是用來表示是否希望HRESULTS轉換爲例外的屬性。還應該指出,你一般*想*使用例外。 HRESULTS只存在,因爲並不是所有的語言都以相同的方式處理異常,所以他們需要一個非異常機制來報告異常。一旦進入自己的語言,HRESULT應該(理想情況下)轉換爲您的語言的本機異常機制。 – 2011-06-27 14:44:27

+1

這不是你想要使用'[PreserveSig]'的唯一原因。有一些COM接口可以更好或更差地使用HRESULT作爲布爾值;這些函數可以返回S_OK,S_FALSE或錯誤值。如果您不使用'[PreserveSig]',則無法知道它是否返回了S_OK或S_FALSE。這不僅適用於S_FALSE,而且適用於任何非錯誤的HRESULT。這樣做的COM類很幸運,但它們確實存在。 – Sven 2011-06-27 17:07:32

+0

還有一個非常奇怪的'IProgressDialog.HasUserCancelled'方法,它甚至不會返回'HRESULT'(如接口方法的其餘部分所做的那樣),而是返回一個'BOOL'。 (幾乎肯定是Windows 95中原始界面中的一個錯誤,現在爲了兼容性而凍結) – 2011-06-30 13:33:00

相關問題