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:
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.
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.
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.
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.
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.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:
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á.
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