Berücksichtigt COM interop .NET AppDomain-Grenzen für das Laden von Baugruppen?

8

Hier ist das Kernproblem: Ich habe eine .NET-Anwendung, die COM-Interop in einer separaten AppDomain verwendet. Das COM-Zeug scheint Baugruppen in die Standarddomäne und nicht in die Anwendungsdomäne zu laden, von der das COM-Material aufgerufen wird.

Was ich wissen möchte, ist: Ist dies das erwartete Verhalten, oder mache ich etwas falsches, damit diese COM-bezogenen Assemblies in die falsche AppDomain geladen werden? Bitte sehen Sie eine detailliertere Beschreibung der Situation unten ...

Die Anwendung besteht aus 3 Baugruppen: - Die Haupt-EXE, der Einstiegspunkt der Anwendung. - common.dll, enthält nur eine Schnittstelle IController (im Stil IPlugin) - controller.dll, enthält eine Controller-Klasse, die IController und MarshalByRefObject implementiert. Diese Klasse erledigt die ganze Arbeit und verwendet COM-Interop, um mit einer anderen Anwendung zu interagieren.

Der relevante Teil der Haupt-EXE sieht so aus:

%Vor%

Die common.dll enthält nur diese zwei Dinge:

%Vor%

Und die controller.dll enthält diese Klasse (die auch das COM-Interop-Zeug aufruft):

%Vor%

Beim ersten Ausführen der Anwendung sieht Assembly.GetAssemblies () wie erwartet aus, wobei common.dll in beiden AppDomains geladen wird und controller.dll nur in die Controller-Domäne geladen wird. Nach dem Aufruf von c.Run () sehe ich jedoch, dass Assemblys, die sich auf die COM-Interop-Elemente beziehen, in die Standard-AppDomain geladen wurden und NICHT in die AppDomain, von der aus das COM-Interop stattfindet.

Warum könnte das passieren?

Und wenn Sie interessiert sind, hier ein bisschen Hintergrund:

Ursprünglich war dies eine 1 AppDomain-Anwendung. Das COM-Zeug, mit dem es verbunden ist, ist eine Server-API, die über lange Zeiträume nicht stabil ist. Wenn eine COMException (ohne nützliche Diagnosedaten zu seiner Ursache) aus dem COM-Code auftritt, muss die gesamte Anwendung neu gestartet werden, bevor die COM-Verbindung wieder funktioniert. Durch einfaches erneutes Verbinden mit dem COM-Anwendungsserver werden sofort wieder COM-Ausnahmen ausgelöst. Um das zu bewältigen, habe ich versucht, das COM-Interop-Zeug in eine separate AppDomain zu verschieben, so dass ich die AppDomain entladen kann, in der es auftritt, ein neues erstellen und neu starten, ohne die Anwendung manuell neu starten zu müssen . Das war die Theorie sowieso ...

    
Xiaofu 28.10.2008, 06:25
quelle

3 Antworten

16

Leider wird eine COM-Komponente in Process Space und nicht im Kontext einer Anwendungsdomäne geladen. Daher müssen Sie Ihre nativen DLLs manuell abbrechen (freigeben und entladen) (gilt für COM und P / Invoke). Eine Appdomain einfach zu zerstören wird Ihnen nicht gut tun, aber das erneute Starten des Prozesses sollte nicht notwendig sein, um den COM-Status zurückzusetzen (das einfache erneute Erstellen der COM-Objekte sollte auch funktionieren), klingt vielleicht wie ein Fehler innerhalb des Komponenten-Provider-Codes Sie können es ansprechen?)

Referenzen

(TechNet) Prozessadressraum

(MSDN) Anwendungsdomänen

(MSDN) -Begrenzungen: Prozesse und Anwendungsdomänen

    
Shaun Wilson 06.11.2009, 04:43
quelle
2

Hier ist der Beweis, dass Shaun Wilsons Antwort richtig ist

    
Jeff K. 11.01.2013 17:26
quelle
0

Machen Sie Ihren Controller-MBR nicht. Erstellen Sie einen kleinen Proxy, der den Controller in der zweiten Domäne lädt und startet. Auf diese Weise wird Controller dll nicht in der ersten Domäne geladen.

    
Sunny Milenov 28.10.2008 15:52
quelle