2008-10-28 28 views
8

Aquí está el problema central: Tengo una aplicación .NET que está usando COM interop 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.¿La interoperabilidad COM respeta los límites del Dominio de aplicación .NET para la carga de ensamblaje?

Lo que quiero saber es: ¿es este comportamiento esperado, o estoy haciendo algo mal para causar que estos ensamblados relacionados con COM se carguen en el AppDomain incorrecto? Por favor, consulte 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 pertinente de la EXE principal se parece a esto:

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 common.dll solamente 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 la información de interoperabilidad COM):

public class Controller: IController, MarshalByRefObject 

Cuando ejecuta por primera vez la aplicación, Assembly.GetAssem blies() 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á interesado, aquí hay un poco de historia:

Originalmente esta era una aplicación de dominio de aplicación 1. 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) del 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 fue la teoría de todos modos ...

+0

fyi, si alguien más echa un vistazo a esto, son las DLL de la API de HP Quality Center las que me dan este problema. Lo solucioné haciendo que la aplicación se reiniciara, pero aún estaría realmente interesado en por qué estaba sucediendo esto. – Xiaofu

Respuesta

16

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 restablecer el estado COM (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

(TechNet) Process Address Space

(MSDN) Application Domains

(MSDN) Boundaries: Processes and AppDomains

+0

Gracias por su respuesta, Shaun. Ha pasado tanto tiempo ahora que no puedo recordar si intenté simplemente recrear los objetos COM, pero sospecho que lo hice. Cuando tenga tiempo, intentaré probar tus sugerencias. Mientras tanto, +1 por mencionar el espacio de proceso. – Xiaofu

+0

Así que todavía no he tenido la oportunidad de probar esto, pero en realidad respondiste la pregunta principal, así que la marcaré como respondida. Muchas gracias por la participación de todos. – Xiaofu

+0

Y sí, sospecho que es un error en el código del proveedor, especialmente porque la causa del error que me lleva a intentar descargar y volver a cargar el componente COM es un verdadero misterio. Debería volver a examinar mi propio código nuevamente algún día antes de culpar a alguien más. – Xiaofu

0

No haga su MBR controlador. 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.

+0

Hola Sunny, Esa fue la idea detrás de usar la interfaz IController en un dll común. Controller.dll no se carga en el dominio predeterminado. La actividad de interoperabilidad COM por parte de la clase Controller en el dominio del controlador parece provocar que las DLL relacionadas con COM se carguen en el dominio predeterminado. – Xiaofu

+0

ACTUALIZACIÓN: el uso de un proxy para crear y ejecutar el controlador en el otro dominio tiene el mismo efecto. Controller.dll NO se carga en el AppDomain predeterminado (ese no era el problema), pero las cosas de interoperabilidad COM parecen seguir cargando ensamblados COM en el dominio predeterminado. – Xiaofu

+0

¿Intentó cargar los ensamblados de interoperabilidad manualmente en el segundo dominio y no retransmitir en el autocargador? –

2

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

Com App Domain

Cuestiones relacionadas