出于某种原因,每当我的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
总是被指定为非零值。您可能提供的任何见解表示赞赏。感谢。
答案 0 :(得分:15)
GetProcAddress只有ANSI风格,因此我们通过告诉它在编组字符串参数时始终使用ANSI来帮助运行时。我们还阻止运行时查找不存在的GetProcAddressA,因为C#的默认设置是将ExactSpelling设置为false。
答案 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的额外包袱的情况下首先计算出正确的输入。