LoadLibrary не сбой на отсутствующей DLL: почему? - PullRequest
1 голос
/ 27 апреля 2011

Я уверен, что мне не хватает чего-то очевидного в документации.Я звоню 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 без видимой причины.Есть идеи, почему я не получаю сообщение об ошибке?

Ответы [ 5 ]

8 голосов
/ 27 апреля 2011

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

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

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

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

7 голосов
/ 27 апреля 2011

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

[DllImport("kernel32.dll", SetLastError=true)]
private static extern IntPtr LoadLibrary(string dllToLoad);
2 голосов
/ 27 апреля 2011

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

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

из MSDN:

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

2 голосов
/ 27 апреля 2011

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

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibrary(string dllToLoad);
2 голосов
/ 27 апреля 2011

Вы должны указать в своем атрибуте 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...