.net - Secuencia de carga del conjunto de interoperabilidad COM
regasm (1)
Creo que encontré la respuesta a su problema en el manual primario de ensambladuras de interoperabilidad de Microsoft. Los PIA se manejan de forma diferente en Visual Studio:
Cuando un usuario intenta agregar una referencia a una biblioteca de tipos que tiene un PIA registrado, Visual Studio usará silenciosamente el PIA registrado en lugar de volver a importar la biblioteca de tipos con Tlbimp. Esto asegura que el PIA se use siempre que sea posible.
Esto significa que cuando agrega una referencia a su propio IA al proyecto, Visual Studio verificará si hay un PIA registrado para este objeto COM. Los PIA de Outlook se registran bajo la siguiente clave:
HKEY_CLASSES_ROOT/CLSID/{0006F023-0000-0000-C000-000000000046}/InprocServer32/12.0.0.0
Assembly="Microsoft.Office.Interop.Outlook, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C"
De lo que entiendo por anular el registro de la PIA usando la herramienta Regasm debería quitar la clave y volver a agregar la referencia a su propia IA debería dar el resultado esperado.
Sin embargo, Microsoft no recomienda usar IA personalizados si hay un PIA disponible. No entiendo la razón exacta de esto, pero supongo que esto podría estar relacionado con las optimizaciones de cálculo y tener definiciones de tipo únicas.
Hay un problema de referencia de ensamblaje muy extraño y un problema de carga que experimento con mi complemento de Outlook. Aquí están los detalles (una larga historia :)):
Tengo un antiguo complemento de Outlook, escrito y compilado usando .Net 1.1. El complemento se carga usando un shim no administrado en su propio dominio de aplicación. Funciona bien, con .Net 2.0, incluso si 1.1 no está presente en la máquina del usuario.
El complemento utiliza un ensamblado de interoperabilidad de Outlook personalizado, creado por VS 2003 en relación con Outlook 2000, y luego reconstruye para que tenga un nombre fuerte (como es mi complemento).
En el proyecto de complemento me refiero solo a este conjunto de interoperabilidad personalizado, sin referencia a los ensamblajes de interoperabilidad MS oficiales.
Cuando este complemento se usa en un entorno con Outlook 2007 y .Net 2.0, donde los ensamblados de interoperabilidad MS oficiales están instalados en GAC, por alguna razón veo que el complemento se carga y los usa.
En el código de la clase Connect, tengo una directiva using:
using Outlook;
que es el espacio de nombre de mi ensamblado de interoperabilidad personalizado.
En Connect ctor tengo estas líneas de código (agregadas para fines de prueba):
Assembly.LoadFrom(PATHTOMYASSEMBLY + "Interop.Outlook.dll");
Type type = typeof(Outlook.ApplicationClass);
logger.Debug("Outlook.Application full type is: {0}", type.AssemblyQualifiedName);
Esto produce:
El tipo completo de Outlook.Application es: Outlook.ApplicationClass, Interop.Outlook, Version = 9.0.0.0, Culture = neutral, PublicKeyToken = 4cfbdc5349cf59d8
Que es exactamente lo que esperaba.
El problema es que cuando se llama a OnConnection (aplicación de objeto, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom), veo en el registro (tengo un enlace al evento AssemblyLoad del dominio actual) que MS interopera el ensamblaje también está cargado:
private void app_domain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
Assembly loadedAssembly = args.LoadedAssembly;
logger.Debug("Assembly {0} is loaded from: {1}", loadedAssembly.FullName, loadedAssembly.GlobalAssemblyCache ? "GAC" : loadedAssembly.Location);
}
Salida:
Assembly Microsoft.Office.Interop.Outlook, Version = 12.0.0.0, Culture = neutral, PublicKeyToken = 71e9bce111e9429c se carga desde: GAC
Mi método OnConnection comienza así:
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
{
Type type = application.GetType();
logger.Debug("OnConnection application object''s full type is: {0}", type.AssemblyQualifiedName);
Outlook.Application applicationObject = (Outlook.Application)application;
Esto produce:
El tipo completo del objeto de la aplicación OnConnection es: Microsoft.Office.Interop.Outlook.ApplicationClass, Microsoft.Office.Interop.Outlook, Version = 12.0.0.0, Culture = neutral, PublicKeyToken = 71e9bce111e9429c
Esto es realmente extraño, como se puede ver en la próxima línea que puedo enviar con éxito a Outlook. La aplicación sin ningún problema.
Lo he comprobado con Reflector, y mi conjunto NO hace referencia a los ensamblados de interoperabilidad de Microsoft de ninguna manera. Lo mismo para mi Interop.Outlook.dll.
Entonces, ¿alguien sabe lo que está pasando? ¿Cuál es la respuesta para estas preguntas?
¿Por qué carga los ensambles de Microsoft en absoluto?
¿Cómo es posible emitir entre clases / interfaces no relacionadas, definidas en diferentes ensamblajes?
NOTA: He creado un nuevo complemento, muy simple, que no hace nada, solo carga. Podría reproducir el problema, entonces, realmente, ¿alguien sabe cómo CLR decide qué interopera cargar y de dónde? Además en GAC, ¿hay otro lugar (registro ???) donde exista un enlace entre un objeto COM y la interoperabilidad que requiere?