c# - ¿La interopera COM respeta los límites del Dominio de aplicaciones.NET para la carga del ensamblaje?
com-interop appdomain (3)
Aquí está el problema principal: tengo una aplicación .NET que está utilizando interoperabilidad COM en un dominio de aplicación separado. Las cosas COM parecen cargar ensamblajes en el dominio predeterminado, en lugar del dominio de aplicación desde el que se llama el material COM.
Lo que quiero saber es: ¿es este comportamiento esperado, o estoy haciendo algo mal para hacer que estos ensamblados relacionados con COM se carguen en el AppDomain incorrecto? Por favor, vea una descripción más detallada de la situación a continuación ...
La aplicación consta de 3 conjuntos: - el EXE principal, el punto de entrada de la aplicación. - common.dll, que contiene solo una interfaz IController (en el estilo IPlugin) - controller.dll, que contiene una clase de controlador que implementa IController y MarshalByRefObject. Esta clase hace todo el trabajo y usa interoperabilidad COM para interactuar con otra aplicación.
La parte relevante del EXE principal se ve así:
AppDomain controller_domain = AppDomain.CreateDomain("Controller Domain");
IController c = (IController)controller_domain.CreateInstanceFromAndUnwrap("controller.dll", "MyNamespace.Controller");
result = c.Run();
AppDomain.Unload(controller_domain);
Common.dll solo contiene estas 2 cosas:
public enum ControllerRunResult{FatalError, Finished, NonFatalError, NotRun}
public interface IController
{
ControllerRunResult Run();
}
Y el controller.dll contiene esta clase (que también llama a las cosas de interoperabilidad COM):
public class Controller: IController, MarshalByRefObject
Cuando ejecuta por primera vez la aplicación, Assembly.GetAssemblies () se ve como se esperaba, con common.dll cargado en ambos AppDomains, y controller.dll solo se está cargando en el dominio del controlador. Después de llamar a c.Run (), sin embargo, veo que los ensamblados relacionados con las cosas de interoperabilidad COM se han cargado en el AppDomain predeterminado, y NO en el AppDomain desde el que se está llevando a cabo la interoperabilidad COM.
¿Por qué podría estar ocurriendo esto?
Y si estás interesado, aquí hay un poco de historia:
Originalmente, esta era una aplicación de 1 AppDomain. El material COM con el que interactúa es una API de servidor que no es estable durante largos períodos de uso. Cuando se produce una COMException (sin información de diagnóstico útil sobre su causa) desde el material COM, toda la aplicación debe reiniciarse antes de que la conexión COM funcione nuevamente. La simple reconexión al servidor de la aplicación COM da como resultado de inmediato excepciones COM. Para hacer frente a esto, he tratado de mover las cosas de interoperabilidad COM en un Dominio de Aplicación separado para que cuando se produzcan las COMExcepciones misteriosas, pueda descargar el DominioDeaplicación en el que ocurre, crear uno nuevo y comenzar de nuevo, todo sin tener que reiniciar manualmente la aplicación . Esa era la teoría, de todos modos...
No hagas tu controlador MBR. Cree un pequeño proxy, que carga el controlador en el segundo dominio y lo inicia. De esta forma, el controlador dll no se cargará en el primer dominio.
Aquí está la prueba de que la respuesta de Shaun Wilson es correcta
Desafortunadamente, un componente COM se carga dentro de Process Space y no dentro del contexto de un AppDomain. Por lo tanto, deberá desmontar manualmente (Liberar y descargar) sus archivos DLL nativos (se aplica tanto a COM como a P / Invocar). Simplemente destruyendo un appdomain no te servirá de nada, pero reaparecer todo el proceso no debería ser necesario para reiniciar el estado COM (simplemente la recreación de los objetos COM también debería funcionar normalmente, esto suena como un error dentro del código de proveedores de componentes, tal vez pueden abordarlo?)
Referencias