C# GetProcAddress возвращает ноль
По какой-то причине всякий раз, когда мое приложение на C# .NET 2.0 вызывает GetProcAddress
он всегда возвращает ноль.
public class MyClass
{
internal static class UnsafeNativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool SetDllDirectory(string lpPathName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
}
private void MyFunc()
{
IntPtr _dllHandle;
IntPtr _fptr;
string _fullPath = ".\\mydll.dll";
string _procName = "MyDllFunc";
_dllHandle = UnsafeNativeMethods.LoadLibrary(_fullPath);
_fptr = UnsafeNativeMethods.GetProcAddress(_dllHandle, _procName); // <-- Always returns zero.
}
}
Я уверен, что имя функции написано правильно, и _fullPath
предположительно правильно, потому что _dllHandle
всегда присваивается ненулевое значение. Любое понимание, которое вы можете предоставить, приветствуется. Благодарю.
4 ответа
GetProcAddress поставляется только в формате ANSI, поэтому мы помогаем среде выполнения, указав ему всегда использовать ANSI при маршалинге строкового параметра. Мы также запрещаем среде выполнения поиск несуществующего GetProcAddressA, поскольку по умолчанию для C# установлено значение ExactSpelling, равное false.
Вам действительно нужно добавить проверку ошибок. По крайней мере, проверьте, если _dllHandle!= IntPtr.Zero. Кроме того, в зависимости от текущего рабочего каталога это опасно, используйте Assembly.GetEntryAssembly().Location, чтобы получить полное имя пути.
Название функции, вероятно, неверно. Экспорт имеет тенденцию быть украшенным, как _MyDllFunc или _MyDllFunc@4. Более дико, если он был скомпилирован компилятором C++. Используйте Dumpbin.exe /exports в вашей DLL, чтобы увидеть настоящие имена.
Возвращаясь к обработке ошибок, используйте SetLastWin32Error в атрибуте [DllImport]. Бросьте Win32Exception, если функция возвращает false или IntPtr.Zero.
Изменить: я вижу реальную проблему. Использование CharSet.Auto для GetProcAddress() неверно. Очень неудачно, это почти единственная функция Windows API, которая имеет только версию ANSI. Вы должны использовать CharSet.Ansi. Хорошее место, чтобы получить правильные объявления [DllImport] - pinvoke.net
Вы не показали, как вы экспортируете функцию из DLL, но я подозреваю, что проблема в том, что экспортированное имя не то, что вы представляете. Вы можете запустить dumpbin /exports mydll.dll
для просмотра экспорта DLL, чтобы проверить имя.
Если вы покажете фрагмент кода экспорта, я мог бы дать более прямой совет. Вы можете попробовать украсить экспортированную функцию с extern "C"
исключить искажение имени в качестве теста.
Ваш экспорт в файле.DEF для DLL совпадает с вводом здесь? Ты можешь использовать dumpbin
чтобы узнать, что экспортируется, за другими ответами здесь.
Что является основной ошибкой Win32 на GetProcAddress()
за GetLastError()
?
Вы можете попробовать это в нативном коде, чтобы сначала отработать правильные вводы без дополнительного багажа P/Invoke.