问题
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