Pergunta

Eu tenho alguns aplicativos (alguns nativa, alguns .NET) que usam arquivos de manifesto para que eles possam ser implantado em completa isolamento, sem necessidade de qualquer registro COM global. Por exemplo, a dependência do servidor dbgrid32.ocx com é declarada como segue no arquivo myapp.exe.manifest que fica na mesma pasta como 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 para a mesma pasta, juntamente com o 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>

Esta tudo bem funciona, mas manter esses arquivos de manifesto manualmente é um pouco de dor. Existe uma maneira para gerar esses arquivos automaticamente? Idealmente, eu gostaria apenas de declarar a dependência do aplicativo em uma lista de servidores COM (tanto nativa e .NET) e depois deixar o resto ser gerado automaticamente. É possível?

Foi útil?

Solução

Parece que a solução perfeita ainda não existe. Para resumir algumas pesquisas:

Make My Manifest ( ligação )

Essa ferramenta verifica um projeto VB6 para procurar dependências COM, mas também suporta declaração manual das dependências COM ligação tardia (ou seja, aqueles usados ??via CreateObject).

Curiosamente, isso coloca ferramenta todas as informações sobre as dependências dentro do manifesto do aplicativo. A exe aplicação e suas dependências são descritas como um único conjunto que consiste em vários ficheiros. 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:

  • apenas para VB6 aplicativos, começa de arquivo de projeto VB6. Vergonha, porque muito do que ele faz realmente não tem nada a ver com VB6.
  • Aplicação de estilo assistente, não adequado para integrar em uma compilação processo. Este não é um grande problema se o seu dependências não mudam muito.
  • gratuito sem fonte, arriscado confiar nele porque ele poderia tornar-se abandonware a qualquer momento.

Eu não testar se ele suporta .NET com bibliotecas.

regsvr42 ( codeproject ligação )

Esta ferramenta de linha de comando gera arquivos de manifesto para bibliotecas COM nativas. Ele invoca DllRegisterServer e depois espiona o auto-registo, uma vez que acrescenta informações no registro. Ele também pode gerar um manifesto cliente para aplicações.

Este utilitário não suporta .NET COM bibliotecas, uma vez que estes não expõem uma rotina DllRegisterServer.

O utilitário é escrito em C ++. O código fonte está disponível.

Mt.exe

Parte do SDK do Windows (pode ser descarregado a partir de MSDN ), o que você já tem, se você tiver Visual studio instalado. É documentado aqui . Você pode gerar arquivos de manifesto para bibliotecas COM nativos com ele assim:

mt.exe -tlb:mycomlib.ocx -dll:mycomlib.ocx -out:mycomlib.ocx.manifest

Você pode gerar arquivos de manifesto para .NET COM bibliotecas com ele assim:

mt.exe -managedassemblyname:netlib.dll -nodependency -out:netlib.dll.manifest

No entanto, existem alguns problemas com esta ferramenta:

  • O primeiro trecho não gerará atributos ProgID clientes quebra que utilizar CreateObject com ProgIDs.
  • O segundo trecho irá gerar elementos <runtime> e <mvid> que precisam ser retirados antes Os manifestos realmente trabalho.
  • Geração dos manifestos cliente para aplicações não é suportado.

Talvez as futuras versões do SDK irá melhorar esta ferramenta, eu testei o do 6.0a Windows SDK (Vista).

Outras dicas

Com a tarefa MSBuild GenerateApplicationManifest I gerou um manifesto no comando linha idêntica à manifesto Visual Studio gera. Eu suspeito que Visual Studio usa o GenerateApplicationManifest durante a construção. Abaixo está o meu script de construção que pode ser executado a partir da linha de comando usando msbuild "build.xml msbuild"

Graças à Dave Templin e sua post que me apontou o a GenerateApplicationManifest tarefa , e MSDN do < a href = "http://msdn.microsoft.com/en-us/library/6wc2ccdc.aspx" rel = "noreferrer"> documentação adicional da tarefa .

build.xml

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="Build">
        <ItemGroup>
            <File Include='MyNativeApp.exe'/>
            <ComComponent Include='Com1.ocx;Com2.ocx'/>
        </ItemGroup>
        <GenerateApplicationManifest
            AssemblyName="MyNativeApp.exe"
            AssemblyVersion="1.0.0.0"
            IsolatedComReferences="@(ComComponent)"
            Platform="x86"
            ManifestType="Native">
            <Output
                ItemName="ApplicationManifest"
                TaskParameter="OutputManifest"/>
        </GenerateApplicationManifest>
    </Target>   
</Project>

fazer meu manifesto (MMM) é uma boa ferramenta para fazer isso. Também é possível escrever um script para processar toda a sua DLL / OCX arquivos usando Mt.exe para gerar um manifesto para cada um e, em seguida, fundi-los todos juntos. MMM é geralmente melhor / mais fácil, porque ele também lida com lotes de especiais / casos estranhos.

Você pode usar autônoma Faça gira meu manifesto off para gerar manifesta diretamente em compilações automatizadas. Ele usa um arquivo de script para adicionar componentes COM dependia. Este é um trecho das ini amostra com os comandos disponíveis:

# Unattended MMM script
#
# Command names are case-insensitive. Reference of supported commands:
#
# Command: Identity
#
#   Appends assemblyIdentity and description tags.
#
#   Parameters       <exe_file> [name] [description]
#      exe_file      file name can be quoted if containing spaces. The containing folder 
#                    of the executable sets base path for relative file names
#      name          (optional) assembly name. Defaults to MyAssembly
#      description   (optional) description of assembly
#
# Command: Dependency
#
#   Appends dependency tag for referencing dependent assemblies like Common Controls 6.0, 
#     VC run-time or MFC
#
#   Parameters       {<lib_name>|<assembly_file>} [version] [/update]
#     lib_name       one of { comctl, vc90crt, vc90mfc }
#     assembly_file  file name of .NET DLL exporting COM classes
#     version        (optional) required assembly version. Multiple version of vc90crt can
#                    be required by a single manifest
#     /update        (optional) updates assembly_file assembly manifest. Spawns mt.exe
#
# Command: File
#
#   Appends file tag and collects information about coclasses and interfaces exposed by 
#     the referenced COM component typelib.
#
#   Parameters       <file_name> [interfaces]
#     file_name      file containing typelib. Can be relative to base path
#     interfaces     (optional) pipe (|) separated interfaces with or w/o leading 
#                    underscore
#
# Command: Interface
#
#   Appends comInterfaceExternalProxyStub tag for inter-thread marshaling of interfaces
#
#   Parameters       <file_name> <interfaces>
#     file_name      file containing typelib. Can be relative to base path
#     interfaces     pipe (|) separated interfaces with or w/o leading underscore
#
# Command: TrustInfo
#
#   Appends trustInfo tag for UAC user-rights elevation on Vista and above
#
#   Parameters       [level] [uiaccess]
#     level          (optional) one of { 1, 2, 3 } corresponding to { asInvoker, 
#                    highestAvailable, requireAdministrator }. Default is 1
#     uiaccess       (optional) true/false or 0/1. Allows application to gain access to 
#                    the protected system UI. Default is 0
#
# Command: DpiAware
#
#   Appends dpiAware tag for custom DPI aware applications
#
#   Parameters       [on_off]
#     on_off         (optional) true/false or 0/1. Default is 0
#
# Command: SupportedOS
#
#   Appends supportedOS tag
#
#   Parameters       <os_type>
#     os_type        one of { vista, win7 }. Multiple OSes can be supported by a single 
#                    manifest
#

Ele será executado em 32 ou 64 bits do Windows.

Para preencher os ProgIDs que Mt.exe não inclui, você pode chamar ProgIDFromCLSID de procurá-los a partir do registro. Isso requer registro COM tradicional antes de completar o arquivo de manifesto, mas, posteriormente, o arquivo de manifesto será auto-suficiente.

Este código C # adiciona os ProgIDs para 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;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top