Nie można załadować biblioteki DLL (nie można znaleźć modułu HRESULT: 0x8007007E)

113

Mam bibliotekę dll z niezarządzanym kodem API C ++, którego potrzebuję w mojej aplikacji .NET 4.0. Ale przy każdej metodzie, którą próbuję załadować moją bibliotekę dll, pojawia się błąd:

Nie można załadować biblioteki DLL „MyOwn.dll”: nie można znaleźć określonego modułu. (Wyjątek od HRESULT: 0x8007007E)

Przeczytałem i wypróbowałem kilka rozwiązań, które znalazłem w Internecie. Nic nie działa..

Próbowałem użyć następujących metod:

[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);

Kiedy próbowałem postępować zgodnie z tym artykułem i kiedy uruchamiam ten przykład (z pobranego kodu), działa on bez problemu (używany plik dll znajduje się w folderze bin / debug)

Skopiowałem mój plik dll (wraz ze wszystkimi plikami, od których zależy, do mojego folderu bin).

Próbowałem też tego podejścia, ale otrzymałem ten sam błąd:

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

Jakieś sugestie?

Ingimar Andresson
źródło

Odpowiedzi:

90

Z tego, co pamiętam w systemie Windows, kolejność wyszukiwania biblioteki dll to:

  1. Bieżący katalog
  2. Folder systemowy C:\windows\system32 or c:\windows\SysWOW64(dla procesu 32-bitowego w wersji 64-bitowej).
  3. Czytanie ze Pathzmiennej środowiskowej

Oprócz tego sprawdzę zależności biblioteki DLL, przewodnik po zależnościach dostarczony z Visual Studio może Ci tutaj pomóc, można go również pobrać bezpłatnie: http://www.dependencywalker.com

display101
źródło
4
stwierdziłem, że brakuje niektórych zależności (Oracle i niektóre biblioteki DLL z IE). Konieczność zainstalowania Oracle od mojego dll zależy that..then będę wiedzieć :) Znaleziony problem z DependencyWalker;)
Ingimar Andresson
Bez obaw, zaoszczędziło mi to wielu godzin drapania głowy, świetne małe narzędzie! :-)
display101
1
+1 do Keitha Halligana za zasugerowanie DependencyWalker. Powiedział mi, że nie wszystkie zależności mają ten sam typ procesora (x86 / x64). Skopiowałem wszystkie pliki, które miały ten sam typ procesora, do folderu bin mojej aplikacji i to rozwiązało problem.
DiligentKarma
6
Każda biblioteka DLL, którą mogę znaleźć w moim systemie, ma DependencyWalker, który twierdzi, że występuje błąd z różnymi typami procesorów - nawet System.Web.Mvc.dll. Jest tu jakiś fałszywy alarm.
PandaWood
2
W moim przypadku problem polegał na próbie załadowania biblioteki DLL C ++ skompilowanej do debugowania. To wymaga środowiska uruchomieniowego debugowania C ++, co oznacza, że ​​musisz zainstalować program Visual Studio. Lub ponownie skompiluj bibliotekę DLL do wydania i zainstaluj dystrybucję środowiska wykonawczego C ++.
RenniePet
42

Możesz użyć narzędzia dumpbin, aby znaleźć wymagane zależności DLL:

dumpbin /DEPENDENTS my.dll

Dzięki temu dowiesz się, które biblioteki DLL muszą zostać załadowane. Szczególnie zwróć uwagę na plik MSVCR * .dll. Widziałem, że kod błędu pojawia się, gdy nie jest zainstalowany poprawny pakiet redystrybucyjny Visual C ++.

„Pakiety redystrybucyjne Visual C ++ dla programu Visual Studio 2013” ​​można pobrać z witryny internetowej firmy Microsoft. Instaluje c: \ windows \ system32 \ MSVCR120.dll

W nazwie pliku 120 = 12,0 = Visual Studio 2013.

Uważaj, aby mieć odpowiednią wersję programu Visual Studio (10.0 = VS 10, 11 = VS 2012, 12.0 = VS 2013 ...) odpowiednią architekturę (x64 lub x86) dla platformy docelowej biblioteki DLL, a także musisz uważać na kompilacje debugowania. Kompilacja debugowania biblioteki DLL zależy od pliku MSVCR120d.dll, który jest wersją biblioteki do debugowania, która jest instalowana z programem Visual Studio, ale nie przez pakiet redystrybucyjny.

Anthony Hayward
źródło
5
dodanie pakietów redystrybucyjnych VS C ++ to było dla mnie wszystko! potrzebna wersja 10.0 (2010). Dzięki mucho !!!
Thiago Silva
Czy istnieje sposób, aby stwierdzić, czy wymagane są 64-bitowe czy 32-bitowe wersje składników redystrybucyjnych?
BVB
1
dumpbin / ALL powie Ci, czy my.dll to x86 z x64
Anthony Hayward
1
Dla tych, którzy nadal cierpią z powodu tego problemu, jeśli używasz debugbinarnego, wersja redystrybucyjna C ++ runtime musi być dokładnie taka sama, jak ta, w której ją zbudowałeś.
skyline75489
Komentarz @ skyline75489 uratował mi dzień. Biblioteka C ++ działała dobrze na moim komputerze, ale nie udało się załadować wszędzie indziej z powodu połączenia VS z wersją msvcr do debugowania.
szpieg
14

To jest `` kludge '', ale możesz go przynajmniej użyć do przetestowania poczytalności: Spróbuj zakodować na stałe ścieżkę do biblioteki DLL w swoim kodzie

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

Powiedziawszy to; w moim przypadku działanie dumpbin /DEPENDENTSzgodnie z sugestią @ anthony-hayward i skopiowanie ponad 32-bitowych wersji bibliotek DLL wymienionych tam do mojego katalogu roboczego rozwiązało ten problem.

Wiadomość jest trochę myląca, ponieważ to nie jest „moja” biblioteka dll, której nie można załadować - to zależności

czarny
źródło
12

Biblioteka DLL musi znajdować się w folderze bin.

W Visual Studio dodaję dll do mojego projektu (NIE w References, ale „Dodaj istniejący plik”). Następnie ustaw właściwość „Kopiuj do katalogu wyjściowego” dla biblioteki dll na „Kopiuj, jeśli nowsza”.

Jeremy Thompson
źródło
11

Spróbuj wprowadzić pełną ścieżkę dll. Jeśli to nie zadziała, spróbuj skopiować dll do folderu system32.

Headpuster
źródło
3
czy można mieć wszystkie zależności w folderze System32, a mój plik dll w innym miejscu?
Ingimar Andresson
Zależności będą również przeszukiwane zgodnie z kolejnością ścieżki wyszukiwania dll systemu Windows, określoną przez stackoverflow.com/a/9003290/4434329
4

Upewnij się, że wszystkie zależności Twojej własnej biblioteki DLL są obecne w pobliżu biblioteki DLL lub w System32.

Felice Pollano
źródło
4

Jest jedna bardzo zabawna rzecz (i ma to techniczne znaczenie), która może zmarnować twoje godziny, więc pomyśl o udostępnieniu jej tutaj -

Stworzyłem projekt aplikacji konsoli ConsoleApplication1i projekt biblioteki klas ClassLibrary1.

Cały kod, który tworzył p / invoke, był obecny w ClassLibrary1.dll. Tak więc przed debugowaniem aplikacji z Visual Studio po prostu skopiowałem niezarządzany zestaw C ++ ( myUnmanagedFunctions.dll) do \bin\debug\katalogu ClassLibrary1projektu, aby można go było załadować w czasie wykonywania przez CLR.

Ciągle otrzymywałem

Nie można załadować biblioteki DLL

błąd przez godziny. Później zdałem sobie sprawę, że wszystkie takie niezarządzane asemblery, które mają zostać załadowane, muszą zostać skopiowane do \bin\debugkatalogu projektu startowego, ConsoleApplication1który zwykle jest formularzem win, konsolą lub aplikacją internetową.

Więc bądź ostrożny Current Directory w zaakceptowanej odpowiedzi faktycznie oznacza Current Directorygłówny plik wykonywalny, z którego rozpoczyna się proces aplikacji. Wygląda na oczywistą rzecz, ale czasami może tak nie być.

Wyciągnięta lekcja - Zawsze umieszczaj niezarządzane biblioteki DLL w tym samym katalogu, co plik wykonywalny startowy, aby upewnić się, że można go znaleźć.

RBT
źródło
Dla mnie to też naprawiło. Dziwnie się czuje umieszczanie bibliotek DLL w głównym projekcie zamiast w projekcie, który ich używa ...
Sean Duggan
@SeanDuggan, ponieważ jest to „biblioteka dynamicznego łączenia”, co oznacza, że ​​jest używana (ładowana) w czasie wykonywania, w przeciwieństwie do bibliotek statycznych, które są używane podczas łączenia.
m4l490n
Próbowałem dodać dll do bin\Debugi obj\Debugkatalogów i ciśgle sekcji „Nie można DLL load”
m4l490n
3

Włącz rejestrowanie fuzji, zobacz to pytanie, aby uzyskać wiele porad, jak to zrobić. Debugowanie problemów z ładowaniem aplikacji w trybie mieszanym może być prawdziwym problemem. Rejestrowanie fuzji może być bardzo pomocne.

Chris O
źródło
2

Upewnij się, że ustawiłeś element docelowy platformy kompilacji na x86 lub x64, aby był zgodny z biblioteką DLL - która może zostać skompilowana dla platformy 32-bitowej.

Zgoda
źródło
2

Jeśli projekty DLL i .NET są w tym samym rozwiązaniu i chcesz skompilować i uruchomić oba za każdym razem, możesz kliknąć prawym przyciskiem myszy właściwości projektu .NET, Zdarzenia kompilacji, a następnie dodać coś podobnego do następującego do zdarzenia po kompilacji wiersz poleceń:

copy $(SolutionDir)Debug\MyOwn.dll .

Jest to w zasadzie linia DOS i możesz dostosować ją w zależności od tego, gdzie budowana jest biblioteka DLL.

SharpC
źródło
2

Miałem ten sam problem, kiedy wdrożyłem moją aplikację do testowania komputera. Problem polegał na tym, że komputer deweloperski miał msvcp110d.dllimsvcr110d.dll nie komputer testowy.

Dodałem moduł scalający „Visual Studio C ++ 11.0 DebugCRT (x86)” w InstalledSheild i zadziałał. Mam nadzieję, że będzie to pomocne dla kogoś innego.

kakopappa
źródło
2

W moim przypadku jedna niezarządzana biblioteka dll była zależna od innej, której brakowało. W takim przypadku błąd wskaże istniejącą bibliotekę dll zamiast brakującej, co może być naprawdę mylące.

Tak właśnie stało się w moim przypadku. Mam nadzieję, że to pomoże komuś innemu.

Rahatur
źródło
1

Myślę, że twoja niezarządzana biblioteka potrzebuje manifestu.
Oto jak dodać go do swojego pliku binarnego. i tutaj dlaczego.

Podsumowując, kilka wersji biblioteki redystrybucyjnej może być zainstalowanych w twoim pudełku, ale tylko jedna z nich powinna odpowiadać twojej aplikacji i może nie być domyślna, więc musisz powiedzieć systemowi, jakiej wersji potrzebuje twoja biblioteka, dlatego manifest.

Eugenio Miró
źródło
1

Konfiguracja : 32-bitowy system Windows 7

Kontekst : Zainstalowałem sterownik PCI-GPIB, przez który nie mogłem się komunikować z powodu wspomnianego problemu.

Krótka odpowiedź : Zainstaluj ponownie sterownik.

Długa odpowiedź : Użyłem również Dependency Walker , który zidentyfikował kilka brakujących modułów zależności. Od razu pomyślałem, że to musiała być nieudana instalacja sterownika. Nie chciałem sprawdzać i przywracać każdego brakującego pliku.

Fakt, że nie mogłem znaleźć dezinstalatora w obszarze Programy i funkcje Panelu sterowania, jest kolejnym wskaźnikiem złej instalacji. Musiałem ręcznie usunąć kilka plików * .dll w katalogu \ system32 i klucze rejestru, aby umożliwić ponowną instalację sterownika.

Problem rozwiązany.

Nieoczekiwaną częścią było to, że nie wszystkie moduły zależności zostały rozwiązane. Niemniej jednak można teraz odwołać się do interesującego nas pliku * .dll.

icernos
źródło
1

Natknąłem się na ten sam problem, w moim przypadku miałem dwie 32-bitowe szt. Jeden z zainstalowanym .NET4.5, a drugi to świeży komputer.

moja 32-bitowa dll cpp (kompilacja w trybie wydania) działała dobrze z zainstalowanym komputerem .NET, ale nie na nowym komputerze, na którym pojawił się poniższy błąd

Nie można załadować biblioteki DLL „PrinterSettings.dll”: nie można znaleźć określonego modułu. (Wyjątek od HRESULT: 0x8007007E)

Wreszcie,

Właśnie zbudowałem swój projekt w konfiguracji trybu debugowania i tym razem moja biblioteka cpp dll działała dobrze.

Abu Muhammad
źródło
0

Napotkano również ten sam problem podczas korzystania z niezarządzanego pliku dll c / c ++ w środowisku C #.

1.Sprawdzono kompatybilność biblioteki dll z procesorem 32-bitowym lub 64-bitowym.

2.Sprawdzono poprawne ścieżki do folderu DLL .bin, system32 / sysWOW64 lub podaną ścieżkę.

3.Sprawdzono, czy brakuje plików PDB (Baza danych programów). Ten film wideo daje najlepsze zrozumienie plików pdb.

Podczas uruchamiania 32-bitowego kodu binarnego C / C ++ w systemie 64-bitowym może to wynikać z niezgodności platformy. Możesz to zmienić w Build> Configuration manager.

Yuresh Karunanayake
źródło
0

Napotkałem ten sam problem podczas importu C ++ Dll w .Net Framework +4, odznaczyłem Project-> Properties-> Build-> Prefer 32-bit i rozwiązałem go dla mnie.

Mamo Ghandi
źródło