Domanda

Ecco il problema principale: ho un'applicazione .NET che utilizza interoperabilità COM in un AppDomain separato. La roba COM sembra ricaricare gli assembly nel dominio predefinito, anziché l'AppDomain da cui viene chiamata la roba COM.

Quello che voglio sapere è: questo comportamento previsto o sto facendo qualcosa di sbagliato per causare il caricamento di questi assembly relativi a COM nell'AppDomain errato? Si prega di consultare una descrizione più dettagliata della situazione di seguito ...

L'applicazione è composta da 3 assiemi: - il file EXE principale, il punto di ingresso dell'applicazione. - common.dll, contenente solo un'interfaccia IController (nello stile IPlugin) - controller.dll, contenente una classe Controller che implementa IController e MarshalByRefObject. Questa classe fa tutto il lavoro e usa l'interoperabilità COM per interagire con un'altra applicazione.

La parte rilevante del file EXE principale è simile al seguente:

AppDomain controller_domain = AppDomain.CreateDomain("Controller Domain");
IController c = (IController)controller_domain.CreateInstanceFromAndUnwrap("controller.dll", "MyNamespace.Controller");
result = c.Run();
AppDomain.Unload(controller_domain);

Il common.dll contiene solo queste 2 cose:

public enum ControllerRunResult{FatalError, Finished, NonFatalError, NotRun}
public interface IController
{
    ControllerRunResult Run();
}

E controller.dll contiene questa classe (che chiama anche roba di interoperabilità COM):

public class Controller: IController, MarshalByRefObject

Quando si esegue l'applicazione per la prima volta, Assembly.GetAssemblies () appare come previsto, con common.dll che viene caricato in AppDomains e controller.dll solo nel dominio del controller. Dopo aver chiamato c.Run (), tuttavia, vedo che gli assembly relativi agli elementi di interoperabilità COM sono stati caricati nell'AppDomain predefinito e NON nell'AppDomain da cui si sta verificando l'interoperabilità COM.

Perché potrebbe accadere?

E se sei interessato, ecco un po 'di background:

Inizialmente si trattava di 1 applicazione AppDomain. La roba COM con cui si interfaccia è un'API del server che non è stabile per lunghi periodi di utilizzo. Quando si verifica una COMException (senza utili informazioni diagnostiche sulla causa) dall'interfaccia COM, l'intera applicazione deve essere riavviata prima che la connessione COM funzioni di nuovo. La semplice riconnessione al server delle app COM comporta di nuovo eccezioni COM immediate. Per far fronte a questo ho provato a spostare le cose di interoperabilità COM in un AppDomain separato in modo che quando si verifica il mistero COMExceptions posso scaricare l'AppDomain in cui si verifica, crearne uno nuovo e ricominciare, tutto senza dover riavviare manualmente l'applicazione . Questa era la teoria comunque ...

È stato utile?

Soluzione

Sfortunatamente, un componente COM viene caricato all'interno di Process Space e non nel contesto di un AppDomain. Pertanto, sarà necessario abbattere manualmente (Rilascio e scarico) le DLL native (vale sia per COM che per P / Invoke). La semplice distruzione di un dominio non ti gioverà, ma la rigenerazione dell'intero processo non dovrebbe essere necessaria per ripristinare lo stato COM (anche semplicemente ricreare gli oggetti COM dovrebbe funzionare normalmente, questo suona come un bug nel codice dei fornitori di componenti, forse possono affrontarlo?)

Riferimenti

(TechNet) Spazio indirizzo processo

(MSDN) Domini applicazione

(MSDN) Confini: processi e AppDomains

Altri suggerimenti

Ecco la prova che la risposta di Shaun Wilson è corretta

Dominio app Com

Non creare l'MBR del controller. Crea un piccolo proxy, che carica il controller nel secondo dominio e lo avvia. In questo modo Controller dll non verrà caricato nel primo dominio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top