Não foi possível carregar a DLL (não foi possível encontrar o módulo HRESULT: 0x8007007E)

113

Eu tenho uma biblioteca dll com código de API C ++ não gerenciado que preciso usar em meu aplicativo .NET 4.0. Mas todo método que tento carregar minha dll, recebo um erro:

Não foi possível carregar a DLL 'MyOwn.dll': O módulo especificado não foi encontrado. (Exceção de HRESULT: 0x8007007E)

Eu li e tentei várias soluções que encontrei na internet. Nada funciona..

Tentei usar os seguintes métodos:

[DllImport("MyOwn.dll",  CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs((UnmanagedType.I4))]
public static extern Int32 MyProIni(string DBname, string DBuser_pass,
    string WorkDirectory, ref StringBuilder ErrorMessage);

Quando tentei seguir este artigo e quando executo este exemplo (a partir do código baixado), ele funciona sem problemas (a dll usada está na pasta bin / debug)

Copiei minha dll (junto com todos os arquivos dos quais ela depende para minha pasta bin).

Eu também tentei essa abordagem, mas obtive o mesmo erro:

[DllImportAttribute(MyOwnLibDllPath, EntryPoint="TMproIni")]
[return: MarshalAs(UnmanagedType.I4)]
public static extern  int MyproIni(string DBname, string DBuser_pass, 
    string WorkDirectory, ref StringBuilder ErrorMessage);

Alguma sugestão?

Ingimar Andresson
fonte

Respostas:

90

Pelo que me lembro no Windows, a ordem de pesquisa por uma dll é:

  1. Diretório atual
  2. Pasta do sistema, C:\windows\system32 or c:\windows\SysWOW64(para processo de 32 bits na caixa de 64 bits).
  3. Leitura da Pathvariável de ambiente

Além disso, eu verificaria as dependências da DLL, o dependencywalker fornecido com o Visual Studio pode ajudá-lo aqui, ele também pode ser baixado gratuitamente: http://www.dependencywalker.com

display101
fonte
4
encontrou algumas dependências faltando (Oracle e algumas dll do IE). Preciso instalar o Oracle, pois minha dll depende disso ... então eu saberei :) Encontrei o problema com DependencyWalker;)
Ingimar Andresson
Não se preocupe, ele economizou muitas horas de coçar a cabeça para mim, excelente ferramenta! :-)
display101
1
+1 para Keith Halligan por sugerir DependencyWalker. Ele me disse que nem todas as dependências tinham o mesmo tipo de CPU (x86 / x64). Copiei todos os arquivos que tinham o mesmo tipo de CPU para a pasta bin do meu aplicativo e isso resolveu o problema.
DiligentKarma
6
Cada dll que posso encontrar no meu sistema tem DependencyWalker, alegando que há um erro com diferentes tipos de CPU - até mesmo System.Web.Mvc.dll. Há algum tipo de alarme falso aqui.
PandaWood
2
No meu caso, o problema era tentar carregar uma DLL C ++ compilada para Debug. Isso precisa do tempo de execução de depuração C ++, o que significa que você precisa instalar o Visual Studio. Ou recompile a DLL para lançamento e instale o tempo de execução C ++ distribuível.
RenniePet
42

Você pode usar a ferramenta dumpbin para descobrir as dependências DLL necessárias:

dumpbin /DEPENDENTS my.dll

Isso informará quais DLLs sua DLL precisa carregar. Particularmente, preste atenção ao MSVCR * .dll. Eu vi seu código de erro ocorrer quando o Visual C ++ Redistributable correto não está instalado.

Você pode obter os "Pacotes redistribuíveis do Visual C ++ para Visual Studio 2013" no site da Microsoft. Ele instala c: \ windows \ system32 \ MSVCR120.dll

No nome do arquivo, 120 = 12.0 = Visual Studio 2013.

Tenha o cuidado de ter a versão certa do Visual Studio (10.0 = VS 10, 11 = VS 2012, 12.0 = VS 2013 ...) arquitetura certa (x64 ou x86) para a plataforma de destino de sua DLL e também deve ser cuidadoso. depurar compilações. A compilação de depuração de uma DLL depende do MSVCR120d.dll, que é uma versão de depuração da biblioteca, instalada com o Visual Studio, mas não pelo pacote redistribuível.

Anthony Hayward
fonte
5
adicionar os redistribuíveis VS C ++ foi tudo para mim! necessário v10.0 (2010). Obrigada mucho !!!
Thiago Silva
Existe alguma maneira de saber se as versões de 64 bits ou 32 bits dos redistribuíveis são necessárias?
BVB
1
dumpbin / ALL dirá se my.dll é x86 de x64
Anthony Hayward,
1
Para aqueles que ainda sofrem com esse problema, se você usar debugbinário, a versão redistribuível do tempo de execução C ++ precisa ser exatamente a mesma de onde você a construiu.
skyline75489
O comentário de @ skyline75489 salvou o dia para mim. A biblioteca C ++ funcionou bem na minha máquina, mas falhou ao carregar em todos os outros lugares devido ao VS ligá-la à versão de depuração do msvcr.
espião
14

Este é um 'kludge', mas você poderia pelo menos usá-lo para um teste de sanidade: tente codificar o caminho para a DLL em seu código

[DllImport(@"C:\\mycompany\\MyDLL.dll")]

Tendo dito isto; no meu caso, executar dumpbin /DEPENDENTSconforme sugerido por @antony-hayward e copiar versões de 32 bits das DLLs listadas lá para meu diretório de trabalho resolveu esse problema para mim.

A mensagem é um pouco enganosa, porque não é "minha" dll que não pode ser carregada - são as dependências

Preto
fonte
12

A DLL deve estar na pasta bin.

No Visual Studio, adiciono a dll ao meu projeto (NÃO nas referências, mas em "Adicionar arquivo existente"). Em seguida, defina a propriedade "Copiar para diretório de saída" para a dll como "Copiar se mais recente".

Jeremy Thompson
fonte
11

Tente inserir o caminho completo da dll. Se não funcionar, tente copiar a dll para a pasta system32.

Headpuster
fonte
3
tudo bem ter todas as dependências na pasta System32 e minha dll em outro lugar?
Ingimar Andresson
As dependências também serão pesquisadas de acordo com a ordem do caminho de pesquisa do Windows DLL, conforme especificado por stackoverflow.com/a/9003290/4434329
4

Certifique-se de que todas as dependências de sua própria dll estejam presentes perto da dll ou em System32.

Felice Pollano
fonte
4

Há uma coisa muito engraçada (e de relevância técnica) que pode desperdiçar suas horas, então pensei em compartilhá-la aqui -

Criei um projeto de aplicativo de console ConsoleApplication1e um projeto de biblioteca de classes ClassLibrary1.

Todo o código que estava fazendo o p / invoke estava presente em ClassLibrary1.dll. Portanto, antes de depurar o aplicativo do visual studio, simplesmente copiei o assembly não gerenciado C ++ ( myUnmanagedFunctions.dll) para o \bin\debug\diretório do ClassLibrary1projeto para que ele possa ser carregado em tempo de execução pelo CLR.

Eu continuei recebendo o

Incapaz de carregar DLL

erro por horas. Mais tarde, percebi que todos os assemblies não gerenciados que devem ser carregados precisam ser copiados para o \bin\debugdiretório do projeto de inicialização, ConsoleApplication1que geralmente é um formulário Win, console ou aplicativo da web.

Portanto, seja cauteloso, pois Current Directoryna resposta aceita, na verdade, significa o Current Directoryexecutável principal de onde o processo de inscrição está começando. Parece uma coisa óbvia, mas às vezes pode não ser.

Lição aprendida - sempre coloque as dlls não gerenciadas no mesmo diretório do executável de inicialização para garantir que possam ser encontradas.

RBT
fonte
Isso também consertou as coisas para mim. Parece meio estranho colocar as DLLs no projeto principal em vez do projeto que as está usando ...
Sean Duggan
@SeanDuggan é porque é uma "biblioteca de vinculação dinâmica", o que significa que é usada (carregada) em tempo de execução, ao contrário de bibliotecas estáticas que são usadas em tempo de vinculação.
m4l490n
Eu tentei adicionar a dll para o bin\Debuge os obj\Debugdiretórios e eu continuo recebendo o "Unable to DLL load"
m4l490n
3

Ligue o registro de fusão, veja esta pergunta para muitos conselhos sobre como fazer isso. Depurar problemas de carregamento de aplicativos de modo misto pode ser uma verdadeira dor de cabeça. O registro de fusão pode ser uma grande ajuda.

Chris O
fonte
2

Certifique-se de definir o Build Platform Target para x86 ou x64 para que seja compatível com sua DLL - que pode ser compilada para uma plataforma de 32 bits.

Grantly
fonte
2

Se os projetos DLL e .NET estão na mesma solução e você deseja compilar e executar ambos sempre, pode clicar com o botão direito do mouse nas propriedades do projeto .NET, eventos de compilação e adicionar algo como o seguinte ao evento Pós-compilação linha de comando:

copy $(SolutionDir)Debug\MyOwn.dll .

É basicamente uma linha do DOS e você pode ajustar com base em onde sua DLL está sendo construída.

SharpC
fonte
2

Eu tive o mesmo problema quando implantei meu aplicativo para testar o PC. O problema foi o desenvolvimento PC teve msvcp110d.dlle msvcr110d.dllmas não o PC de teste.

Eu adicionei o módulo de mesclagem "Visual Studio C ++ 11.0 DebugCRT (x86)" no InstalledSheild e funcionou. Espero que isso seja útil para outra pessoa.

kakopappa
fonte
2

No meu caso, uma dll não gerenciada dependia de outra que estava faltando. Nesse caso, o erro apontará para a dll existente em vez da ausente, o que pode ser muito confuso.

Isso é exatamente o que aconteceu no meu caso. Espero que isso ajude mais alguém.

Rahatur
fonte
1

Acho que sua biblioteca não gerenciada precisa de um manifesto.
Aqui está como adicioná-lo ao seu binário. e aqui está o porquê.

Em resumo, várias versões de biblioteca redistribuível podem ser instaladas em sua caixa, mas apenas uma delas deve satisfazer seu aplicativo, e pode não ser o padrão, então você precisa informar ao sistema a versão de que sua biblioteca precisa, por isso o manifesto.

Eugenio Miró
fonte
1

Configuração : Windows 7 de 32 bits

Contexto : Instalei um driver PCI-GPIB pelo qual não consegui me comunicar devido ao problema mencionado.

Resposta curta : Reinstale o driver.

Resposta longa : Eu também usei o Dependency Walker , que identificou vários módulos de dependência ausentes. Imediatamente, pensei que deveria ter sido uma falha na instalação do driver. Eu não queria verificar e restaurar cada arquivo ausente.

O fato de não ter conseguido encontrar o desinstalador em Programas e Recursos do Painel de Controle é outro indicador de instalação incorreta. Tive que excluir manualmente alguns * .dll em \ system32 e as chaves de registro para permitir a reinstalação do driver.

Problema corrigido.

A parte inesperada foi que nem todos os módulos de dependência foram resolvidos. No entanto, o * .dll de interesse agora pode ser referenciado.

icernos
fonte
1

Eu me deparei com o mesmo problema, no meu caso eu tinha dois PCs de 32 bits. Um com .NET4.5 instalado e outro era um PC novo.

minha dll cpp de 32 bits (versão em modo de versão) estava funcionando bem com o PC instalado em .NET, mas não com um PC novo, onde recebi o erro abaixo

Impossível carregar DLL 'PrinterSettings.dll': O módulo especificado não foi encontrado. (Exceção de HRESULT: 0x8007007E)

finalmente,

Acabei de construir meu projeto na configuração do modo de depuração e desta vez minha dll cpp estava funcionando bem.

Abu Muhammad
fonte
0

Também enfrentou o mesmo problema ao usar o arquivo dll c / c ++ não gerenciado em ambiente c #.

1. Verificou a compatibilidade da dll com CPU de 32 bits ou 64 bits.

2. Verificou os caminhos corretos da pasta DLL .bin, system32 / sysWOW64 ou o caminho fornecido.

3.Verificado se os arquivos PDB (banco de dados do programa) estão faltando. Este vídeo oferece a você uma melhor compreensão sobre os arquivos PDB.

Ao executar o código binário C / C ++ de 32 bits em um sistema de 64 bits, isso pode ocorrer devido à incompatibilidade de plataforma. Você pode alterá-lo em Build> Configuration manager.

Yuresh Karunanayake
fonte
0

Eu enfrentei o mesmo problema ao importar C ++ Dll no .Net Framework +4, desmarquei Project-> Properties-> Build-> Prefer 32-bit e resolveu para mim.

Mamo Ghandi
fonte