Registro libre de activación del componente nativo COM (activex) desde .NET

Tengo una dll nativa (que es un control activex) que necesito usar con mi aplicación .NET sin tener que registrar la dll en el registro.

He leído varias publicaciones en profundidad sobre la activación sin registro, algunas de las mejores son

Una larga de Steve White y Leslie Muller.

Este de samuel jack

Y otro de Mike Makarov.

Y por lo que puedo ver es posible. Sin embargo, varias horas y cientos de pruebas más tarde simplemente no puedo hacer que funcione. He hecho un poco de PInvoking e incluso menos con los controles ActiveX en .NET en mi carrera, por lo que agradecería cualquier aportación de cualquier persona que haya pateado goles en esto antes.

Hasta ahora estoy siguiendo el consejo de Steves, en cuanto a crear una aplicación que funcione y luego tratar de formular la syntax del archivo de manifiesto mediante la ejecución repetida del comando regsvr32 para agregar y eliminar las dll no administradas del registro. Solo una aplicación de consola .Net simple y con cerca de 10 líneas de código …

Una parte sobre la que estoy confundido es la interoperabilidad. Los dll nativos que tengo también están acompañados con envoltorios de tiempo de ejecución administrados (RCW). En mi aplicación .NET agrego referencias a estos RCW y luego puedo consumir las respectivas clases y funciones proporcionadas por los dll no administrados. No estoy fumando a través de dllimport .

Al crear los archivos de manifiesto, no estoy seguro de si debo preocuparme por estos RCW y cómo funcionan en un escenario sin registro, o incluso si deben estar en la salida comstackda.

También he probado varias herramientas como (visor de objetos OLE / COM, Mt.exe desde Windows SDK y regsvr42 de Codeproject). Pero la estructura manifiesta y los GUID necesarios varían entre herramientas y publicaciones.

El estado actual es que recibí una InvalidCastException “No se puede convertir el objeto COM de tipo System .__ ComObject al tipo de interfaz MyFunkyDllLib.FunkyDllControl. Esta operación falló porque la llamada a Interfaz Query en el componente COM para la interfaz con IID ‘{algún guid}’ falló al siguiente error: Biblioteca no registrada.

¿Alguien puede confirmar la syntax correcta para la aplicación y los archivos de manifiesto dll? Las publicaciones en línea incluso varían en el nombre y algunas usan sxs en el nombre ….

Actualización 1: Si bien la respuesta de Joe a continuación no funcionó, me dio una mejor perspectiva de COM libre reg. En las propiedades de la dll Interop (la que se agrega a la referencia del proyecto de la lista de componentes COM instalados en la máquina de desarrollo), cambié la Propiedad aislada a Verdadero. Esto tiene el efecto de hacer que VS dump una copia de la dll COM (no la interoperabilidad, está incrustada en el exe) en la carpeta bin \ debug. VS también crea un myapplication.exe.manifest.

En este archivo de manifiesto es supuestamente suficiente información para reg free com. Encontré otras publicaciones que indicaban éxito con este método, pero en mi caso todavía terminé con la misma InvalidCastException .

Al volver a leer la publicación de Samuel Jacks, probé su método de crear un manifiesto para el archivo exe y la dll COM utilizando la información clsid del manifiesto de salida de VStudio cuando Isolated=true . (También eliminé la sección creada por VS del exe.manifest). ¡Después de cancelar el registro de COM del registro, ahora tengo éxito! La aplicación se inicia y no da error. Por qué este enfoque funciona y no lo Isolated=true No tengo idea porque está más allá de mi conocimiento de manifiestos y ensamblajes.

Sin embargo todavía no estamos en el castillo de magos todavía Toto.

Ahora estoy de vuelta en el mismo problema que publiqué en este hilo SO . Sin embargo, en este escenario las pruebas unitarias no están involucradas. Solo una aplicación de consola simple con 10 líneas de código. Funciona bien cuando está en el modo COM registrado normal, pero no en el modo reg libre.

Después de muchas horas de prueba y error, finalmente obtuve una solución para implementar RegFree COM con éxito. Aquí hay una explicación completa en caso de que ayude a alguien más.

  1. Creo una nueva biblioteca de clases .NET en VS
  2. Haga clic derecho en las referencias y seleccione los componentes COM de interés. (Nota: para que COM esté visible en la lista, deben estar registrados en la máquina de desarrollo. Esto se puede lograr utilizando la herramienta Regsvr32.exe incluida con windows. Al llamar “regsvr32 mycomdll.dll”, se registra en el registro de Windows)
  3. Haga clic con el botón derecho en la referencia COM, goto properties, y luego establezca Isolated = True. Esto tiene el efecto de hacer que VS genere un archivo .manifest que supuestamente contiene todos los detalles de registro necesarios para que un .exe consumidor sepa qué recursos cargar en lugar de consultar el registro. Sin embargo en mi caso fue incompleto. Las llamadas a los métodos de interoperabilidad funcionarán, pero los eventos del componente COM no. Vea el paso 5 para mi solución)
  4. Construye el proyecto. El .manifest debe aparecer en la salida de comstackción.
  5. Abra el manifiesto en el bloc de notas o similar. Dentro de la etiqueta necesitaba agregar una con los elementos apropiados de IID , tlbid y proxyStubClsid32 GUID. Los elementos del manifiesto están documentados en msdn . En mi caso, el proxy / código auxiliar era proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"/> que es el proxy de Windows integrado. El iid y tlbid que descubrí originalmente a través de Process Monitor mientras llamaba regsvr32. Una opción más fácil y confiable que más tarde descubrí fue usar una herramienta como el creador de manifiestos SxS ya que agregó un segundo que originalmente no tenía.
  6. Cree un proyecto exe en VS y haga referencia a la biblioteca construida anteriormente.
  7. Construye el proyecto exe.
  8. Ejecute regsvr32 / u mycomdll.dll. Para eliminar todas las asociaciones de registro.
  9. Ejecutar el exe. En mi caso, las llamadas y los eventos del componente COM en la biblioteca de clases funcionaron perfectamente.

Advertencias: No sé por qué VS no incluye el elemento automáticamente en el .manifest. En el momento de escribir, la única forma de actualizar automáticamente el manifiesto era agregar una tarea de comstackción posterior en VS. En mi caso, copié todo el manifiesto XML en un XML en el proyecto de la biblioteca de clases y luego sobrescribí el archivo .manifest en el resultado de la comstackción.

La prueba unitaria (integración) de la COM es inconsistente. Actualmente en mi caso las llamadas a los métodos de interoperabilidad funcionan, pero los eventos no. Tiene algo que ver con el hecho de que el corredor de prueba no se comstack con el conocimiento de las dependencias y, por lo tanto, no están presentes en el contexto de activación.

Probablemente le falte una statement de biblioteca de tipos … pero ignórela por ahora … En su lugar, haga lo siguiente …

Después de jugar con esto una y otra vez por un tiempo, decidí que la forma más fácil de hacerlo es usar MSBuild y una tarea GenerateApplicationManifest. Lo he estado usando con una aplicación no administrada, pero no veo por qué no funcionaría con una aplicación administrada. Digo “aplicación” … porque mi aplicación está administrada pero tengo bibliotecas COM y ensamblados .NET con clases ComVisible en ellos.

Según su descripción, parece que está tratando de tener COM y no tiene que preocuparse por consumir ensamblados .NET de COM. Puede buscar en MSBUILD y GenerateApplicationManifest para obtener un archivo de ejemplo de MSBuild.

Por lo tanto, asumo que no tendrá que rellenar el atributo “Dependencias” de la tarea. Deberá completar el atributo “IsolatedComReferences” con una lista de sus DLL COM. Pueden ser una simple lista delimitada por punto y coma, pero por lo general están en las declaraciones de “ItemGroup” en el archivo de proyecto de MSBuild. Las DLL de COM deben registrarse en el momento en que genere el manifiesto.

En cuanto a su RCW, no hay nada especial que deba hacer. OMI, no necesitan estar en el manifiesto. .NET tiene una forma de encontrarlos siempre que estén en el mismo directorio que su aplicación / DLL.

Si usa MSBuild, no tendrá que generar manifiestos para su DLL COM … Probablemente ya tengan manifiestos … Por lo general, los asistentes generan manifiestos automáticamente y los incorporan. El único manifiesto que necesitará la información de tipo COM es el manifiesto que genera con MSBuild.

El punto central de los manifiestos utilizados de esta manera es rellenar el espacio del manifiesto con toda la información COM que estaría en el registro.