¿La interoperabilidad COM respeta los límites de la aplicación .NET para la carga de ensamblajes?

StackOverflow https://stackoverflow.com/questions/242391

Pregunta

Este es el problema principal: tengo una aplicación .NET que utiliza interoperabilidad COM en una AppDomain separado. Las cosas de COM parecen estar cargando ensamblajes de nuevo en el dominio predeterminado, en lugar del dominio de aplicación desde el cual se llaman las cosas de COM.

Lo que quiero saber es: ¿es este comportamiento esperado o estoy haciendo algo incorrecto para que estos ensamblados relacionados con COM se carguen en el dominio de aplicación incorrecto? Consulte la descripción más detallada de la situación a continuación ...

La aplicación consta de 3 ensamblajes: - El EXE principal, el punto de entrada de la aplicación. - common.dll, que contiene solo una interfaz IController (en el estilo de IPlugin) - controller.dll, que contiene una clase Controller que implementa IController y MarshalByRefObject. Esta clase hace todo el trabajo y utiliza la 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);

El archivo 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 se llama "interoperabilidad COM"):

public class Controller: IController, MarshalByRefObject

Cuando se ejecuta la aplicación por primera vez, Assembly.GetAssemblies () se ve como se esperaba, con common.dll cargado en AppDomains, y controller.dll solo se carga 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 dominio de aplicación predeterminado, y NO en el dominio de aplicación desde donde se realiza la interoperabilidad COM.

¿Por qué podría estar ocurriendo esto?

Y si estás interesado, aquí tienes un poco de antecedentes:

Originalmente, esta era una aplicación de 1 dominio de aplicación. 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 excepción COMException (sin información de diagnóstico útil sobre su causa) a partir de COM, la aplicación debe reiniciarse antes de que la conexión COM funcione nuevamente. Simplemente volviendo a conectar con el servidor de aplicaciones COM se obtienen nuevamente excepciones inmediatas. Para hacer frente a esto, he tratado de mover las cosas de interoperabilidad COM a un dominio de aplicación separado para que, cuando se produzcan las misteriosas excepciones COM, pueda descargar el dominio de aplicación en el que aparece, crear uno nuevo y comenzar de nuevo, todo sin tener que reiniciar manualmente la aplicación . Esa era la teoría de todos modos ...

¿Fue útil?

Solución

Lamentablemente, un componente COM se carga en Process Space y no dentro del contexto de un dominio de aplicación. Por lo tanto, deberá desarmar (liberar y descargar) manualmente sus DLL nativos (se aplica tanto a COM como a P / Invoke). El simple hecho de destruir un dominio de aplicación no le servirá de nada, pero volver a generar todo el proceso no debería ser necesario para restablecer el estado COM (simplemente recrear el (los) objeto (s) COM normalmente debería funcionar, esto suena como un error en el código del proveedor de componentes, tal vez pueden abordarlo?)

Referencias

(TechNet) Espacio de direcciones del proceso

Dominios de aplicación (MSDN)

(MSDN) Límites: Procesos y dominios de aplicaciones

Otros consejos

Aquí está la prueba de que la respuesta de Shaun Wilson es correcta

Com App Domain

No hagas tu controlador MBR. Cree un proxy pequeño, que carga el Controlador en el segundo dominio y lo inicia. De esa manera, la DLL del controlador no se cargará en el primer dominio.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top