2011-07-05 52 views
3

COM interop向我證明了什麼。我有一個簡單的託管DLL包含一個WPF窗口。我有一個簡單的ViewController類,最終會啓動這個窗口,但現在有一個空方法,什麼都不做。COM Interop在調用託管DLL時拋出EEMessageException

我已經爲這個託管DLL創建了一個託管包裝器,它公開了一個爲COM託管註冊的接口。我可以調用我的託管包裝確定。我可以在我的託管包裝器DLL的入口點顯示一個MessageBox。但是,如果我試圖在DLL中的這個ViewController類上調用ANY方法,我得到以下結果:

MfcVSApp1.exe中的0x7c812aeb(kernel32.dll)的第一次機會異常:Microsoft C++異常:EEMessageException at內存位置0x0012cb30 ..

這一切顯然昨天工作。現在一些代碼:

我的包裝實體:

[Guid("83C799E0-9808-40c2-A1AB-80BCB77A3B18")] 
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
    [ComVisible(true)] 
    public interface IMaryln 
    { 
     void GetEphemeris(DateTime date, double latitude, double longitude); 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="date"></param> 
     /// <param name="latitude"></param> 
     /// <param name="longitude"></param> 
     void GetEphemeris1(Int64 millSecsSince1970, double latitude, double longitude); 
    } 

[Guid("144DB386-D8EF-41a8-B9B1-57EE8A64600C")] 
    [ClassInterface(ClassInterfaceType.None)] 
    [ProgId("ManagedProxy.Maryln")] 
    [ComVisible(true)] 
    public class Maryln : IMaryln 
    { 
     #region IMaryln Members 

     public Maryln() 
     { 
      System.Diagnostics.Debugger.Launch(); 
     } 

     public void GetEphemeris(DateTime date, double latitude, double longitude) 
     { 
      //new EphemerisViewController().GetEphemeris(date, latitude, longitude); 
     } 

     public void GetEphemeris1(Int64 nanoSecsSince1970, double latitude, double longitude) 
     { 
      // This method does not throw. However, it will not be executed 
      // if any method in EphemerisViewController is called. 
      MessageBox.Show("Called from c++" + nanoSecsSince1970.ToString()); 


      try 
      { 
       //new Maryln().Test(); // this will not throw 
       new EphemerisViewController().GetString(); // this will 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      }        
     } 

     public void Test() 
     { 
      MessageBox.Show("maryln test"); 
     } 

     #endregion 
    } 

託管DLL,通過託管包裝DLL引用,包含了用戶控件,這的ViewController:

public class EphemerisViewController 
    {  
     public EphemerisViewController() 
     {   
     }     

     public void GetString() 
     { 
      MessageBox.Show("me"); 
     } 

    } 

這個DLL也註冊了COM互操作,但我沒有選中該選項,因爲它沒有幫助。上師,我需要幫助。這已經消耗了兩個工作日,而且我已經從我開始的地方回到了3個步驟。這一切都在昨天。

加成

本機客戶端消耗我的包裝如下:

void CMfcVSApp1Doc::LaunchEphemrisDialog() 
{ 
    HRESULT hr; 
    CoInitialize(NULL); 
    try 
    {    
     ManagedProxy::IMarylnPtr maryln(__uuidof(ManagedProxy::Maryln));  
     LONG64 time = 1309897499216000000; 
     hr = maryln->GetEphemeris1(time, 0, 0); 
    } 
    catch(...) 
    { 

    } 
} 

另外,我還清理和重建,解決了無數次,但沒有運氣。

回答

1

不知道在這裏發生了什麼,但我決定拋棄這個包裝DLL並從頭創建一個新包。我沒有改變我正在包裝的C#項目,只是爲了看看這兩個項目中的哪一個導致了問題。這種行爲單獨讓我調試了被包裝的C#項目中暴露的每個API。使用Hans P建議的項目調試技術,我能夠進一步調試我的包裝器DLL。我只是能夠看到一個託管的異常而放鬆一下。絕對是向前邁進的一步。

事實證明,每個對EphemerisViewController中包裝的API的調用都拋出了一個管理異常,即無法找到依賴項(位於程序集清單不匹配加載的程序集.... blah..blah。)。我們都知道是什麼原因造成的。

清理程序集引用後,從而消除上述錯誤,然後我可以再次調用我的託管DLL。一方面浪費一天。另一方面學到了很多東西。爲什麼最初的包裝停止工作是超出我的理解,但我很高興放棄。它一直是命名空間損壞和DLL加載問題的組合,但是誰知道。

我正準備拋棄COM互操作並潛入MFC,但男孩,我很高興我堅持我的槍。與C#相比,就我而言,C++開發很糟糕。例如,只要能夠在C#中捕捉到一般的異常,就像我們在C++中捕獲(...)的catch(...)一樣,這是一個很大的好處。所有瘋狂的C++語法和頭部劃傷例程來執行簡單的轉換讓我頭暈目眩。更不用說智能感知,哦智能感知。由於過期的虛擬助手許可證每天都會讓我意識到它處於休眠狀態,並且企業預算緊張,所以我會堅持使用C#一段時間,或許考慮調查諸如Boost之類的C++庫,以防萬一。但是,男孩,我很樂意回到.NET。

在這裏學到的教訓是:用COM互操作,你必須密切關注細節!