Tengo algunas aplicaciones (algunas nativas, algunas .NET) que usan archivos de manifiesto para que se puedan implementar en completo aislamiento , sin requerir ningún registro COM global. Por ejemplo, la dependencia del servidor com dbgrid32.ocx se declara de la siguiente manera en el archivo myapp.exe.manifest que se encuentra en la misma carpeta que myapp.exe:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity type="win32" name="myapp.exe" version="1.2.3.4" />
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="dbgrid32.ocx" version="5.1.81.4" />
</dependentAssembly>
</dependency>
</assembly>
El dbgrid32.ocx se implementa en la misma carpeta, junto con su propio archivo dbgrid32.ocx.manifest:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity type="win32" name="dbgrid32.ocx" version="5.1.81.4" />
<file name="dbgrid32.ocx">
<typelib
tlbid="{00028C01-0000-0000-0000-000000000046}"
version="1.0"
helpdir=""/>
<comClass progid="MSDBGrid.DBGrid"
clsid="{00028C00-0000-0000-0000-000000000046}"
description="DBGrid Control" />
</file>
</assembly>
Todo esto funciona bien, pero mantener estos archivos de manifiesto manualmente es un poco complicado. ¿Hay alguna forma de generar estos archivos automáticamente? Idealmente, solo me gustaría declarar la dependencia de la aplicación en una lista de servidores COM (tanto nativos como .NET) y luego dejar que el resto se genere automáticamente. ¿Es posible?
Respuestas:
Parece que la solución perfecta aún no existe. Para resumir algunas investigaciones:
Hacer mi manifiesto ( enlace )
Esta herramienta escanea un proyecto VB6 para buscar dependencias COM, pero también es compatible con la declaración manual de dependencias COM vinculadas en fecha tardía (es decir, las utilizadas a través de CreateObject).
Curiosamente, esta herramienta pone toda la información sobre las dependencias dentro del manifiesto de la aplicación. El exe de la aplicación y sus dependencias se describen como un solo ensamblado que consta de varios archivos. No me había dado cuenta antes de que esto era posible.
Parece una muy buena herramienta, pero a partir de la versión 0.6.6 tiene las siguientes limitaciones:
No probé si es compatible con las bibliotecas com .NET.
regsvr42 ( enlace de codeproject )
Esta herramienta de línea de comandos genera archivos de manifiesto para bibliotecas COM nativas. Invoca DllRegisterServer y luego espía el registro automático a medida que agrega información al registro. También puede generar un manifiesto de cliente para aplicaciones.
Esta utilidad no es compatible con las bibliotecas COM de .NET, ya que no exponen una rutina DllRegisterServer.
La utilidad está escrita en C ++. El código fuente está disponible.
mt.exe
Parte del SDK de Windows (se puede descargar desde MSDN ), que ya tiene si tiene instalado Visual Studio. Está documentado aquí . Puede generar archivos de manifiesto para bibliotecas COM nativas con él de esta manera:
Puede generar archivos de manifiesto para las bibliotecas COM .NET de esta manera:
Sin embargo, existen algunos problemas con esta herramienta:
<runtime>
y<mvid>
elementos que necesitan ser despojado de delante de los manifiestos de hecho trabajar.Quizás las futuras versiones del SDK mejoren esta herramienta, probé la del SDK de Windows 6.0a (vista).
fuente
Con la tarea GenerateApplicationManifest de MSBuild, generé un manifiesto en la línea de comandos idéntico al manifiesto que genera Visual Studio. Sospecho que Visual Studio usa GenerateApplicationManifest durante la compilación. A continuación se muestra mi script de compilación que se puede ejecutar desde la línea de comandos usando msbuild "msbuild build.xml"
Gracias a Dave Templin y su publicación que me indicó la tarea GenerateApplicationManifest y la documentación adicional de MSDN de la tarea .
build.xml
fuente
Make My Manifest (MMM) es una buena herramienta para hacer esto. También es posible escribir un script para procesar todos sus archivos DLL / OCX usando mt.exe para generar un manifiesto para cada uno y luego fusionarlos todos juntos. MMM suele ser mejor / más fácil, porque también maneja muchos casos especiales / extraños.
fuente
Puede utilizar el spin-off Unattended Make My Manifest para generar manifiestos directamente en compilaciones automatizadas. Utiliza un archivo de secuencia de comandos para agregar componentes COM dependientes. Este es un extracto del ejemplo ini con los comandos disponibles:
Se ejecutará en Windows de 32 o 64 bits.
fuente
Para completar los ProgID que mt.exe no incluye, puede llamar
ProgIDFromCLSID
para buscarlos en el registro. Esto requiere el registro COM tradicional antes de completar el archivo de manifiesto, pero posteriormente, el archivo de manifiesto será autosuficiente.Este código C # agrega los ProgID a todas las clases COM en un manifiesto:
var manifest = XDocument.Load(fileName); var namespaceManager = new XmlNamespaceManager(new NameTable()); namespaceManager.AddNamespace("s", "urn:schemas-microsoft-com:asm.v1"); foreach (var classElement in manifest.XPathSelectElements("s:assembly/s:file/s:comClass", namespaceManager)) { var clsid = Guid.Parse(classElement.Attribute("clsid").Value); int result = ProgIDFromCLSID(ref clsid, out string progId); if (result != S_OK) throw new COMException($"ProgID lookup failed for {clsid}.", result); classElement.SetAttributeValue("progid", progId); } manifest.Save(fileName);
El código se basa en estas definiciones de interoperabilidad:
[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID); const int S_OK = 0;
fuente