由于某些原因,每当我的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总是被分配一个非零值。如果您能提供任何见解,我们将不胜感激。谢谢。
发布于 2010-09-21 02:38:14
GetProcAddress只有ANSI风格,因此我们通过告诉运行时在编组字符串参数时始终使用ANSI来帮助运行时。我们还防止运行库查找不存在的GetProcAddressA,因为C#的默认设置是将ExactSpelling设置为false。
http://www.pinvoke.net/default.aspx/kernel32.getprocaddress
发布于 2010-09-21 02:34:12
你真的需要添加一些错误检查。至少验证_dllHandle != IntPtr.Zero。此外,根据当前工作目录的危险程度,可以使用Assembly.GetEntryAssembly().Location获取完整的路径名。
函数名可能是错误的。导出往往是装饰性的,就像_MyDllFunc或_MyDllFunc@4。如果它是由C++编译器编译的,那就更复杂了。在DLL上使用Dumpbin.exe /exports查看真实名称。
回到错误处理,在DllImport属性中使用SetLastWin32Error。如果函数返回false或IntPtr.Zero,则抛出Win32Exception。
编辑:我看到了真正的问题。对GetProcAddress()使用CharSet.Auto是错误的。非常不幸的是,它是唯一一个只有ANSI版本的Windows API函数。您必须使用CharSet.Ansi。pinvoke.net是获取正确DllImport声明的一个好地方
发布于 2010-09-21 02:33:43
您还没有展示如何从DLL导出函数,但我怀疑问题在于导出的名称并不是您想象的那样。您可以运行dumpbin /exports mydll.dll查看dll的导出以验证名称。
如果您显示导出的代码片段,我可以提供更直接的建议。您可以尝试使用extern "C"修饰导出的函数,以消除作为测试的名称损坏。
https://stackoverflow.com/questions/3754264
复制相似问题