Tenho alguns aplicativos (alguns nativos, alguns .NET) que usam arquivos de manifesto para que possam ser implantados de forma totalmente isolada , sem exigir nenhum registro COM global. Por exemplo, a dependência do servidor dbgrid32.ocx com é declarada da seguinte maneira no arquivo myapp.exe.manifest, que fica na mesma pasta 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>
O dbgrid32.ocx é implantado na mesma pasta, junto com seu próprio arquivo 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>
Tudo isso funciona bem, mas manter esses arquivos de manifesto manualmente é um pouco chato. Existe uma maneira de gerar esses arquivos automaticamente? Idealmente, gostaria apenas de declarar a dependência do aplicativo em uma lista de servidores COM (nativos e .NET) e, em seguida, deixar o resto ser gerado automaticamente. É possível?
Respostas:
Parece que a solução perfeita ainda não existe. Para resumir algumas pesquisas:
Make My Manifest ( link )
Esta ferramenta varre um projeto VB6 para procurar dependências COM, mas também suporta a declaração manual de dependências COM de ligação tardia (ou seja, aquelas usadas via CreateObject).
Curiosamente, essa ferramenta coloca todas as informações sobre as dependências dentro do manifesto do aplicativo. O aplicativo exe e suas dependências são descritos como um único assembly que consiste em vários arquivos. Eu não tinha percebido antes que isso era possível.
Parece uma ferramenta muito boa, mas a partir da versão 0.6.6 tem as seguintes limitações:
Não testei se ele oferece suporte a bibliotecas .NET com.
regsvr42 ( link codeproject )
Esta ferramenta de linha de comando gera arquivos de manifesto para bibliotecas COM nativas. Ele invoca DllRegisterServer e, em seguida, espiona o autorregistro à medida que adiciona informações ao registro. Ele também pode gerar um manifesto de cliente para aplicativos.
Este utilitário não oferece suporte a bibliotecas .NET COM, pois elas não expõem uma rotina DllRegisterServer.
O utilitário foi escrito em C ++. O código-fonte está disponível.
mt.exe
Parte do Windows SDK (pode ser baixado do MSDN ), que você já possui se tiver o Visual Studio instalado. Está documentado aqui . Você pode gerar arquivos de manifesto para bibliotecas COM nativas assim:
Você pode gerar arquivos de manifesto para bibliotecas .NET COM assim:
No entanto, existem alguns problemas com esta ferramenta:
<runtime>
e<mvid>
que precisam ser removidos antes que os manifestos realmente funcionem.Talvez versões futuras do SDK aprimorem essa ferramenta, testei a do Windows SDK 6.0a (vista).
fonte
Com a tarefa MSBuild GenerateApplicationManifest , gerei um manifesto na linha de comando idêntico ao manifesto gerado pelo Visual Studio. Suspeito que o Visual Studio usa GenerateApplicationManifest durante a compilação. Abaixo está o meu script de construção que pode ser executado a partir da linha de comando usando msbuild "msbuild build.xml"
Agradeço a Dave Templin e sua postagem que me indicou a tarefa GenerateApplicationManifest e a documentação adicional do MSDN sobre a tarefa .
build.xml
fonte
Make My Manifest (MMM) é uma boa ferramenta para fazer isso. Também é possível escrever um script para processar todos os seus arquivos DLL / OCX usando mt.exe para gerar um manifesto para cada um e, em seguida, mesclá-los todos juntos. MMM geralmente é melhor / mais fácil, porque também lida com muitos casos especiais / estranhos.
fonte
Você pode usar o spin off Unattended Make My Manifest para gerar manifestos diretamente em compilações automatizadas. Ele usa um arquivo de script para adicionar componentes COM dependentes. Este é um trecho do exemplo de ini com os comandos disponíveis:
Ele será executado no Windows de 32 ou 64 bits.
fonte
Para preencher os ProgIDs que o mt.exe não inclui, você pode ligar
ProgIDFromCLSID
para consultá-los no registro. Isso requer o registro COM tradicional antes de completar o arquivo de manifesto, mas posteriormente, o arquivo de manifesto será autossuficiente.Este código C # adiciona os ProgIDs a todas as classes COM em um manifesto:
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);
O código depende dessas definições de interoperabilidade:
[DllImport("ole32.dll")] static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID); const int S_OK = 0;
fonte