#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.