C # GetProcAddress возвращает ноль - PullRequest
       34

C # GetProcAddress возвращает ноль

11 голосов
/ 20 сентября 2010

По какой-то причине всякий раз, когда мое приложение на 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 ]

15 голосов
/ 20 сентября 2010

GetProcAddress поставляется только в формате ANSI, поэтому мы помогаем среде выполнения, указав ему всегда использовать ANSI при сортировке строкового параметра.Мы также не разрешаем среде выполнения искать несуществующий GetProcAddressA, поскольку по умолчанию для C # установлено значение ExactSpelling, равное false.

2 голосов
/ 20 сентября 2010

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

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

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


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

1 голос
/ 20 сентября 2010

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

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

0 голосов
/ 20 сентября 2010

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

Что является основной ошибкой Win32 на GetProcAddress(), на GetLastError()?

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

...