Compartilhar via


Solucionando problemas de aplicativos isolados do C/C++ e assemblies lado a lado

O carregamento de um aplicativo do C/C++ poderá falhar se não for possível encontrar as bibliotecas dependentes. Este artigo descreve alguns motivos comuns pelos quais um aplicativo do C/C++ não é carregado e sugere etapas para resolver os problemas.

Se um aplicativo falhar ao se carregado porque ele tem um manifesto que especifica uma dependência de um assembly lado a lado e o assembly não estiver instalado como um assembly particular na mesma pasta que o executável nem no cache de assemblies nativo na pasta %WINDIR%\WinSxS\, uma das seguintes mensagens de erro poderá ser exibida, dependendo da versão do Windows na qual você tentou executar o aplicativo.

  • O aplicativo não foi inicializado corretamente (0xc0000135).

  • Este aplicativo falhou ao iniciar porque a configuração do aplicativo está incorreta. A reinstalação do aplicativo pode corrigir este problema.

  • O sistema não pôde executar o programa especificado.

Se o aplicativo não tiver manifesto e depender de uma DLL que o Windows não consegue encontrar nos locais de pesquisa típicos, uma mensagem de erro semelhante a essa poderá ser exibida:

  • Esse aplicativo não foi iniciado porque uma DLL necessária não foi encontrada. Reinstalar o aplicativo pode corrigir esse problema.

Se o aplicativo for implantado em um computador que não tenha o Visual Studio e ele falhar com mensagens de erro semelhantes às anteriores, verifique o seguinte:

  1. Siga as etapas descritas em Entender as dependências de um Aplicativo do Visual C++. O navegador de dependências pode mostrar a maioria das dependências de um aplicativo ou uma DLL. Se você observar que algumas DLLs estão ausentes, instale-as no computador no qual você está tentando executar o aplicativo.

  2. O carregador do sistema operacional usa o manifesto do aplicativo para carregar os assemblies dos quais o aplicativo depende. O manifesto pode ser inserido no binário como um recurso ou instalado como um arquivo separado na pasta do aplicativo. Para verificar se o manifesto está inserido no binário, abra o binário no Visual Studio e procure RT_MANIFEST na lista de recursos. Se você não conseguir encontrar um manifesto inserido, procure na pasta do aplicativo um arquivo com nome parecido com <binary_name>.<extensão>.manifesto.

  3. Se o aplicativo depender de assemblies lado a lado e um manifesto não estiver presente, você precisará garantir que o vinculador gere um manifesto para seu projeto. Marque a opção do vinculador Gerar manifesto na caixa de diálogo Propriedades do Projeto do projeto.

  4. Se o manifesto estiver inserido no binário, verifique se a ID RT_MANIFEST está correta para esse tipo de binário. Para obter mais informações sobre qual ID de recurso usar, confira Usando assemblies lado a lado como um recurso (Windows). Se o manifesto estiver em um arquivo separado, abra-o em um editor XML ou editor de texto. Para obter mais informações sobre manifestos e regras para implantação, confira Manifestos.

    Observação

    Se um manifesto inserido e um arquivo de manifesto separado estiverem presentes, o carregador do sistema operacional usará o manifesto inserido e ignorará o arquivo separado. No entanto, no Windows XP, o oposto é verdadeiro: o arquivo de manifesto separado é usado e o manifesto inserido é ignorado.

  5. Recomendamos que você insira um manifesto em cada DLL porque os manifestos externos são ignorados quando uma DLL é carregada por meio de uma chamada LoadLibrary. Para obter mais informações, confira Manifestos do assembly.

  6. Verifique se todos os assemblies enumerados no manifesto estão instalados corretamente no computador. Cada assembly é especificado no manifesto por nome, número de versão e arquitetura do processador. Se o aplicativo depender de assemblies lado a lado, verifique se esses assemblies estão instalados corretamente no computador para que o carregador do sistema operacional possa encontrá-los, conforme descrito na Sequência de Pesquisa de Assembly. Lembre-se de que assemblies de 64 bits não podem ser carregados em processos de 32 bits e não podem ser executados em sistemas operacionais de 32 bits.

Exemplo

Suponha que temos um aplicativo, appl.exe, que foi criado usando o Visual C++. O manifesto do aplicativo é inserido no appl.exe como o recurso binário RT_MANIFEST, que tem uma ID igual a 1 ou é armazenado como o arquivo separado appl.exe.manifest. O conteúdo deste manifesto é semelhante a este:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Fabrikam.SxS.Library" version="2.0.20121.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3e"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>

Para o carregador do sistema operacional, esse manifesto informa que appl.exe depende de um assembly chamado Fabrikam.SxS.Library, versão 2.0.20121.0, criado para uma arquitetura de processador x86 de 32 bits. O assembly lado a lado dependente pode ser instalado como um assembly compartilhado ou como um assembly particular.

O manifesto do assembly de um assembly compartilhado é instalado na pasta %WINDIR%\WinSxS\Manifests\. Ele identifica o assembly e lista seu conteúdo, ou seja, as DLLs que fazem parte do assembly:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <noInheritable/>
   <assemblyIdentity type="win32" name="Fabrikam.SxS.Library" version="2.0.20121.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3e"/>
   <file name="Fabrikam.Main.dll" hash="3ca5156e8212449db6c622c3d10f37d9adb1ab12" hashalg="SHA1"/>
   <file name="Fabrikam.Helper.dll" hash="92cf8a9bb066aea821d324ca4695c69e55b2d1c2" hashalg="SHA1"/>
</assembly>

Assemblies lado a lado também podem usar arquivos de configuração do editor, também conhecidos como arquivos de política, para redirecionar globalmente aplicativos e assemblies para usar uma versão de um assembly lado a lado em vez de outra versão do mesmo assembly. Você pode verificar as políticas de um assembly compartilhado na pasta %WINDIR%\WinSxS\Policies\. Veja aqui um exemplo de arquivo de política:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

   <assemblyIdentity type="win32-policy" name="policy.2.0.Fabrikam.SxS.Library" version="2.0.20121.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3e"/>
   <dependency>
      <dependentAssembly>
         <assemblyIdentity type="win32" name="Fabrikam.SxS.Library" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3e"/>
         <bindingRedirect oldVersion="2.0.10000.0-2.0.20120.99" newVersion="2.0.20121.0"/>
      </dependentAssembly>
   </dependency>
</assembly>

Este arquivo de política especifica que qualquer aplicativo ou assembly que solicite a versão 2.0.10000.0 desse assembly deve usar a versão 2.0.20121.0, que é a versão atual instalada no sistema. Se uma versão do assembly mencionada no manifesto do aplicativo for especificada no arquivo de política, o carregador procurará uma versão desse assembly especificada no manifesto na pasta %WINDIR%\WinSxS\ e, se essa versão não estiver instalada, o carregamento falhará. E se a versão do assembly 2.0.20121.0 não estiver instalada, o carregamento falhará para os aplicativos que solicitam o assembly versão 2.0.10000.0.

No entanto, o assembly também pode ser instalado como um assembly lado a lado particular na pasta do aplicativo instalado. Se o sistema operacional falhar ao encontrar o assembly como um assembly compartilhado, ele o procurará como um assembly particular, na seguinte ordem:

  1. Verifique a pasta do aplicativo para obter um arquivo de manifesto que tenha o nome <assemblyName>.manifest. Neste exemplo, o carregador tenta localizar Fabrikam.SxS.Library.manifest na pasta que contém o appl.exe. Se encontrar o manifesto, o carregador carregará o assembly da pasta do aplicativo. Se o assembly não for encontrado, o carregamento falhará.

  2. Tente abrir a pasta \<assemblyName>\ na pasta que contém appl.exe e, se \<assemblyName>\ existir, tente carregar um arquivo de manifesto que tenha o nome <assemblyName>.manifest desta pasta. Se o manifesto for encontrado, o carregador carregará o assembly da pasta \<assemblyName>\. Se o assembly não for encontrado, o carregamento falhará.

Para obter mais informações sobre como o carregador pesquisa assemblies dependentes, confira Sequência de Pesquisa de Assembly. Se o carregador não encontrar um assembly dependente como um assembly particular, o carregamento falhará e a mensagem "O sistema não pôde executar o programa especificado" será exibida. Para resolver esse erro, verifique se assemblies dependentes e DLLs que fazem parte deles estão instalados no computador como assemblies particulares ou compartilhados.

Confira também

Conceitos de aplicativos isolados e assemblies lado a lado
Compilando aplicativos isolados do C/C++ e assemblies lado a lado