C# GetProcAddress Returns Zero

萝らか妹 提交于 2019-12-29 05:19:24

问题


For some reason, whenever my C# .NET 2.0 application makes a call to GetProcAddress it always returns zero.

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

I'm sure the function name is spelled correctly, and _fullPath is presumably correct because _dllHandle is always assigned a non-zero value. Any insight you may be able to provide is appreciated. Thanks.


回答1:


GetProcAddress only comes in an ANSI flavor, hence we help the runtime by telling it to always use ANSI when marshalling the string parameter. We also prevent the runtime looking for a non-existent GetProcAddressA, because the default for C# is to set ExactSpelling to false.

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




回答2:


You really need to add some error checking. At least verify if _dllHandle != IntPtr.Zero. Also, depending on the current working directory is dangerous, use Assembly.GetEntryAssembly().Location to get a full path name.

The function name is probably wrong. Exports tends to be decorated, like _MyDllFunc or _MyDllFunc@4. More wildly if it was compiled by a C++ compiler. Use Dumpbin.exe /exports on your DLL to see the real names.

Back to error handling, use SetLastWin32Error in the [DllImport] attribute. Throw Win32Exception if the function returns false or IntPtr.Zero.


Edit: I see the real problem. Using CharSet.Auto for GetProcAddress() is wrong. Very unlucky, it is just about the only Windows API function that only has an ANSI version. You have to use CharSet.Ansi. A good place to get proper [DllImport] declarations is pinvoke.net




回答3:


You have not shown how you export the function from the DLL, but I suspect the problem is that the exported name is not what you thing it is. You can run dumpbin /exports mydll.dll to view the exports of the dll to verify the name.

If you show the a code snippet of the export, I could provide more direct advice. You can try decorate the exported function with extern "C" to eliminate the name mangling as a test.




回答4:


Does your export in the .DEF file for the DLL match the input here? You can use dumpbin to find out what's exported, per other replies here.

What is the underlying Win32 error on GetProcAddress(), per GetLastError()?

You could try this in native code to work out the correct inputs first without the additional baggage of P/Invoke.



来源:https://stackoverflow.com/questions/3754264/c-sharp-getprocaddress-returns-zero

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!