2012-03-27 3 views
1

Ich versuche, ein .NET-Objekt in einem COM-Objekt zu aggregieren (die äußere unbekannt) mit dem folgenden Code:Warum bin ich ein ExecutionEngineException bekommen, wenn COM-Aggregation versucht

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

... 

Gibt es etwas „offensichtlich“ falsch mit diesem Code? Diese Ausnahme lässt mich sehr wenig weiter. Ärgerlich ist auch, dass die Ausnahme nicht immer passiert, obwohl es öfter passiert. Gibt es einen anderen Weg, dies zu erreichen? (dh maragle das innereUnknown IntPtr zu meinem COM-Objekt)

HINWEIS: Ich muss Version 2 des Frameworks und nicht Version 4 ausprobiert haben, und bin, soweit ich weiß, auf dem neuesten Stand.

+0

Versuchen Sie 'comObj.DotNetObj = innerUnknown;'. Der Aufruf von "GetObjectForIUknown" ist nicht erforderlich. – Ben

Antwort

3

Um die Frage zu beantworten, ist der Grund, warum es fehlschlägt, dass das innere Unbekannte das falsche unbekannte ist. Die Methode soll das aktive RCW für ein COM IUnknown abrufen, aber dieses IUnknown ist ein Com-callable-Wrapper für ein verwaltetes Objekt. In jedem Fall benötigt das äußere Objekt den Zeiger innerUnknown. Wenn Sie es geben, versuchen Sie einen Stack-Überlauf in QueryInterface.

In Ihrem obigen Beispiel denkt das .NET-Objekt, dass es vom COM-Objekt aggregiert wurde, aber das COM-Objekt ist nicht bekannt. Angenommen, es handelt sich um Ihr COM-Objekt, müssen Sie es innerUnknown geben und dann ein delegierendes IUnknown implementieren (falls nicht bereits geschehen). Sie müssen GetObjectForIUnknown nicht aufrufen.

Sie machen es irgendwie rückwärts aber. Der übliche Weg besteht darin, dass das COM-Objekt CoCreateInstance aufruft, das sich selbst als das äußere Unbekannte übergibt. Die Laufzeit ruft dann CreateAggregatedObject für Sie auf.


Wenn Sie möchten, dass das .Net-Objekt das COM-Objekt aggregiert, sollten Sie von RCW erben. Dadurch wird das COM-Objekt als ein aggregiertes Objekt erstellt, das Ihren .Net-internen Code an CoCreateInstance weitergibt. Aber es muss ein Objekt sein, das die Aggregation unterstützt.

Wenn Sie möchten, dass das COM-Objekt das .NET-Objekt aggregiert, müssen Sie ein COM-Objekt verwenden, das das tut. Typische Beispiele sind ADO aggregierende OLEDB-Provider, ADSI-aggregierende ADSI-Erweiterungen, WMI (glaube ich). Aber es muss vom Objekt unterstützt werden, Sie können keinem alten Objekt sagen, dass es Sie aggregieren soll. In der Regel tritt es durch das andere Objekt auf, das CoCreateInstance aufruft, das von der .NET-Laufzeit verarbeitet wird, die CreateAggregatedObject für Sie aufruft und das innere Unknown an den Aufrufer zurückgibt.

+0

Danke für die Antwort, es hat tatsächlich funktioniert. Ich musste meine ComImported-Schnittstelle ändern, um den Typ von DotNetObj auf IntPtr (anstelle von Object) und Marshal als SysInt zu setzen. Ich wünschte, die Ausnahme, die ich bekam, war ein bisschen hilfreicher, genauso wie die Dokumentation. Ich merke, dass der Code ein bisschen rückwärts ist, war ein Experiment für ein anderes Problem, das ich habe. – Marcus

+0

@Marcus, Kein Problem. Ich bin mir nicht sicher, wer mich abgelehnt hat! – Ben

Verwandte Themen