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.

http://www.pinvoke.net/default.aspx/kernel32.getprocaddress


вам действительно нужно добавить некоторую проверку ошибок. По крайней мере, проверьте, если _dllHandle != Тип IntPtr.Нуль. Кроме того, в зависимости от текущего рабочего каталога опасно использовать сборку.GetEntryAssembly().Месте, чтобы получить полное имя пути.

имя функции, вероятно, неправильно. Экспорт, как правило, украшен, как _MyDllFunc или _MyDllFunc@4. Более дико, если он был скомпилирован компилятором с++. Используйте Dumpbin.exe / экспорт в вашей DLL, чтобы увидеть реальные имена.

вернуться к ошибке обработка, используйте SetLastWin32Error в атрибуте [DllImport]. Бросьте Win32Exception, если функция возвращает false или IntPtr.Нуль.


Edit: я вижу реальную проблему. Использование CharSet.Авто для GetProcAddress () неверно. Очень не повезло, это как раз о только функция Windows API, которая имеет только версию ANSI. Вы должны использовать CharSet.кодировка ANSI. Хорошим местом для получения правильных деклараций [DllImport] является pinvoke.net


вы не показали, как вы экспортируете функцию из DLL, но я подозреваю, что проблема в том, что экспортированное имя не то, что вы вещь. Вы можете запустить dumpbin /exports mydll.dll просмотреть экспорта ДЛЛ для проверки имени.

Если вы покажете фрагмент кода экспорта, я мог бы предоставить более прямые советы. Вы можете попробовать украсить экспортированную функцию с помощью extern "C" чтобы исключить искажение имени в качестве теста.


ваша экспорта .DEF-файл для DLL соответствует входу здесь? Вы можете использовать dumpbin чтобы узнать, что экспортируется, за другие ответы здесь.

что такое основная ошибка Win32 на GetProcAddress(), per GetLastError()?

вы можете попробовать это в собственном коде, чтобы сначала выработать правильные входные данные без дополнительного багажа P / Invoke.