C#GetProcAddress返回零

时间:2010-09-20 18:24:38

标签: c# dll kernel32 getprocaddress

出于某种原因,每当我的C#.NET 2.0应用程序调用{​​{1}}时,它总是返回零。

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总是被指定为非零值。您可能提供的任何见解表示赞赏。感谢。

4 个答案:

答案 0 :(得分:15)

GetProcAddress只有ANSI风格,因此我们通过告诉它在编组字符串参数时始终使用ANSI来帮助运行时。我们还阻止运行时查找不存在的GetProcAddressA,因为C#的默认设置是将ExactSpelling设置为false。

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

答案 1 :(得分:2)

您确实需要添加一些错误检查。至少验证_dllHandle!= IntPtr.Zero。此外,根据当前工作目录是危险的,使用Assembly.GetEntryAssembly()。Location来获取完整的路径名。

函数名称可能有误。出口倾向于装饰,如_MyDllFunc或_MyDllFunc @ 4。如果它是由C ++编译器编译的话,会更加疯狂。在DLL上使用Dumpbin.exe / exports查看真实姓名。

返回错误处理,在[DllImport]属性中使用SetLastWin32Error。如果函数返回false或IntPtr.Zero,则抛出Win32Exception。


编辑:我看到了真正的问题。使用CharSet.Auto for GetProcAddress()是错误的。非常不走运,它仅仅是 Windows API函数,只有ANSI版本。你必须使用CharSet.Ansi。获得正确[DllImport]声明的好地方是pinvoke.net

答案 2 :(得分:1)

您还没有展示如何从DLL导出函数,但我怀疑问题是导出的名称不是您的意思。您可以运行dumpbin /exports mydll.dll来查看dll的导出以验证名称。

如果您显示导出的代码段,我可以提供更直接的建议。您可以尝试使用extern "C"修饰导出的函数,以消除名称修改作为测试。

答案 3 :(得分:0)

您在DLL的.DEF文件中的导出是否与此处的输入匹配?您可以使用dumpbin来查找导出的内容,以及其他回复。

GetProcAddress()每个GetLastError()的基础Win32错误是什么?

您可以在本机代码中尝试这一点,以便在没有P / Invoke的额外包袱的情况下首先计算出正确的输入。