2011-06-06 75 views
4

除了S_OK(0)的任何結果,我目前正在升級到廣泛使用COM/MFC /項目的異常(誰知道有多少其他技術)。作爲升級的一部分,我們試圖將盡可能多的功能轉移到託管的C#代碼中,但不幸的是有些東西無法移動(因爲我不會介入)。其中一件事就是嚴重濫用COM的一段代碼,並返回HRESULT中的指針,這些指針隨後會轉換爲各種其他COM接口實現對象。我試過下面的代碼的HRESULT轉換爲指針,我可以再從得到的接口:得到一個COM對象扔在C#

 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)?

+2

指針在HRESULT?哇。疼痛。 – 2011-06-06 23:59:43

+2

哦,我的。你可憐的靈魂...... – dkackman 2011-06-07 00:00:49

回答

5

兩個想法:

  1. 找到並殺死(或嚴重致殘) 誰實現了這個庫
  2. 實現託管C++ 的包裝,你將需要直接在 方法調用的HRESULT得到和I 想不到使用interop做 的方法。

EDIT

另一種選擇是在C#申報COM接口,使得每個方法的簽名返回的返回值的HRESULT和用途[出RETVAL]。這將使您能夠獲得並檢查所有方法調用的HRESULT,而不僅僅是拋出COMException的那些調用。

默認情況下,COM互操作類型導入「修復」方法簽名,使得HRESULT返回在託管端被移除,互操作層拋出E_FAIL等異常,實質上拋棄S_OK,S_FALSE等。

This article有一些解釋,並且PreserveSig attriubte文檔有一些附加的細節。

這可能需要您手動聲明所有COM接口,而不是使用tlbimp,但您可能能夠獲得tlbimp以保留COM方法的簽名。

這將可以讓您足不出戶純粹是C#,但在你的鞋子我會去與託管C++,因爲它只是更容易在這種非標準的方式與COM交互從那裏。