2012-03-27 78 views
1

我試圖聚集的COM對象中的.NET對象(外未知)時,使用下面的代碼我得到一個ExecutionEngineException:爲什麼我試圖COM聚集

Object obj = ... // some ComVisible .NET object 

var comObj = (IMyComInterface)Activator.CreateInstance(Type.GetTypeFromProgID("some.progid")); 

var unknown = Marshal.GetIUnknownForObject(comObj); 

var innerUnknown = Marshal.CreateAggregatedObject(unknown, obj); 

// This is where the ExecutionEngineException is thrown.   
var aggObj = Marshal.GetObjectForIUnknown(innerUnknown); 

// Make outer object aware of our dotnet object, say. 
comObj.DotNetObj = aggObj; 

Marshal.Release(unknown); 

... 

,請問有什麼「明顯」錯誤用這個代碼?這個例外讓我很少繼續下去。另外令人討厭的是,這種例外並不總是發生,儘管它經常發生。 有沒有另一種方法來實現這一目標? (即將內部未知的IntPtr編組爲我的COM對象)

注意:我必須定位框架的第2版,並且沒有嘗試版本4,並且據我所知,完全是最新的。

+0

嘗試'comObj.DotNetObj = innerUnknown;'。對'GetObjectForIUknown'的調用是不必要的。 – Ben 2012-03-28 07:55:19

回答

3

要回答這個問題,它失敗的原因是innerUnknown是錯誤的未知數。該方法旨在爲COM IUnknown獲取活動的RCW,但是該IUnknown是託管對象的可調用包裝器。

在任何情況下,外部對象都需要innerUnknown指針。如果你給它一個你試圖給你的那個會在QueryInterface中得到一個堆棧溢出。

在上例中,.Net對象認爲它已被COM對象聚合,但COM對象不知道。假設它是你的COM對象,你需要給它innerUnknown,然後實現一個委託IUnknown(如果你還沒有的話)。你不需要調用GetObjectForIUnknown。

然而,你有點反其道而行之。通常的方法是讓COM對象調用CoCreateInstance將其自身作爲外部未知數傳遞。運行時然後爲你調用CreateAggregatedObject。


如果您希望.Net對象聚合COM對象,則應該從RCW繼承。這將創建COM對象作爲聚合對象,將.Net內部未知內容傳遞給CoCreateInstance。但它必須是一個支持聚合的對象。

如果您希望COM對象聚合.Net對象,則必須使用一個COM對象。典型的例子是ADO聚合OLEDB提供商,ADSI聚合ADSI擴展,WMI(我認爲)。但它必須得到對象的支持,你不能告訴任何舊對象來聚合你。通常它由調用CoCreateInstance的另一個對象發生,該對象由.Net運行時處理,它將爲您調用CreateAggregatedObject,並將innerUnknown傳回給調用者。

+0

謝謝你的回答,它確實有效。我不得不改變我的ComImported接口,將DotNetObj的類型設置爲IntPtr(而不是Object)並將其編組爲SysInt。我希望我得到的例外更有幫助,文檔也一樣。我意識到代碼有點倒退,是我遇到的另一個問題的實驗。 – Marcus 2012-03-28 09:48:08

+0

@馬庫斯,沒問題。不知道是誰低估了我! – Ben 2012-03-28 09:50:42