LoadLibrary не дает сбоя при отсутствии DLL: почему?

#c# #interop

#c# #взаимодействие

Вопрос:

Я уверен, что я упускаю что-то очевидное в документации. Я вызываю LoadLibrary из C # и передаю DLL, которой там нет. Я возвращаюсь, IntPtr.Zero как и следовало ожидать, но при вызове Marshal.GetLastWin32Error я всегда получаю 0.

Вот пример.

 class Program {

    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);

    static void Main(string[] args) {
        IntPtr pDll = LoadLibrary(@"c:NotThere.dll");
        int err = Marshal.GetLastWin32Error();
        Console.WriteLine(err);
        Console.ReadLine();
    }
}
  

Я добавляю подобный код в программу, которая уже не может загрузить DLL без видимой причины. Есть идеи, почему я не получаю сообщение об ошибке?

Комментарии:

1. что произойдет, если вы это сделаете Assembly.LoadFrom(...) ? Неясно, является ли DLL неуправляемой, как я предполагал.

2. вау … так много людей ниже, очевидно, нашли ту же страницу Google, чтобы ответить на этот вопрос… либо это, либо все пишут dllToLoad одинаково…..

3. @JD — Или мы просто добавили флаг в операционный код выше.

4. @0A0D, ты прав, я не уточнил. Это неуправляемая DLL.

5. @JD Некоторые из нас могут ответить на вопросы SO без помощи Google 😉

Ответ №1:

Для регистрации ошибок, чтобы они могли быть прочитаны Marshal.GetLastWin32Error() , вам необходимо иметь SetLastError=true атрибут on DllImport :

 [DllImport("kernel32.dll", SetLastError=true)]
private static extern IntPtr LoadLibrary(string dllToLoad);
  

Ответ №2:

Ваш код не устанавливает флаг атрибута DllImport.SetLastError, что может быть причиной того, что GetLastWin32Error ничего не возвращает:

 [DllImport("kernel32.dll", SetLastError=true)]
private static extern IntPtr LoadLibrary(string dllToLoad);
  

Чтобы определить, почему модули не загружаются, вы должны проверить журналы объединения (если модуль является управляемой сборкой) и / или средство обхода зависимостей.

Имейте в виду, что ошибка загрузки может быть вызвана тем, что не удалось загрузить зависимый модуль (например, распространяемый VC9, от которого зависят все модули C , скомпилированные с помощью компилятора VS2008), и поэтому, даже если модуль совместим с архитектурой и расположен в каталоге с возможностью поиска (таком как каталог приложения или системы), модуль все равно может не загрузиться — Dependency walker очень хорош в выделении такого рода проблем.

Ответ №3:

Вы должны объявить в своем DllImport атрибуте, что вы хотите, чтобы последняя ошибка была зафиксирована с помощью SetLastError поля. Например:

 [DllImport("kernel32.dll", SetLastError=true)]
private static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool FreeLibrary(IntPtr hModule);
  

Ответ №4:

Используйте следующее DllImport :

 [DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibrary(string dllToLoad);
  

Ответ №5:

попробуйте добавить этот атрибут:

 [DllImportAttribute("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]  
  

из msdn:

Возвращает код ошибки, возвращенный последней неуправляемой функцией, которая была вызвана с помощью platform invoke, имеющей атрибут DllImportAttribute.Установлен флаг SetLastError.