C# GetProcAddress 返回零
由于某种原因,每当我的 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
始终分配一个非零值。我们非常感谢您能够提供的任何见解。谢谢。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
GetProcAddress 仅具有 ANSI 风格,因此我们通过告诉运行时在编组字符串参数时始终使用 ANSI 来帮助运行时。我们还阻止运行时查找不存在的 GetProcAddressA,因为 C# 的默认设置是将 ExactSpelling 设置为 false。
http://www.pinvoke.net/default.aspx/kernel32.getprocaddress
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
您确实需要添加一些错误检查。至少验证 _dllHandle != IntPtr.Zero 是否。另外,依赖当前工作目录是危险的,请使用 Assembly.GetEntryAssembly().Location 来获取完整路径名。
函数名称可能是错误的。导出往往会被修饰,例如 _MyDllFunc 或 _MyDllFunc@4。如果它是由 C++ 编译器编译的,那就更疯狂了。在 DLL 上使用 Dumpbin.exe /exports 查看真实姓名。
回到错误处理,在 [DllImport] 属性中使用 SetLastWin32Error。如果函数返回 false 或 IntPtr.Zero,则抛出 Win32Exception。
编辑:我看到了真正的问题。对 GetProcAddress() 使用 CharSet.Auto 是错误的。非常不幸,它只是only Windows API 函数,只有 ANSI 版本。您必须使用 CharSet.Ansi。 pinvoke.net 是获取正确 [DllImport] 声明的好地方
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
您没有展示如何从 DLL 导出该函数,但我怀疑问题在于导出的名称不是您想要的名称。您可以运行 dumpbin /exports mydll.dll 来查看 dll 的导出以验证名称。
如果您显示导出的代码片段,我可以提供更直接的建议。您可以尝试使用
extern "C"
修饰导出的函数,以消除名称损坏作为测试。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.您在 DLL 的 .DEF 文件中导出的内容是否与此处的输入相匹配?您可以根据此处的其他回复使用
dumpbin
来查找导出的内容。根据
GetLastError()
,GetProcAddress()
上的底层 Win32 错误是什么?您可以在本机代码中尝试此操作,首先计算出正确的输入,而无需 P/Invoke 的额外包袱。
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()
, perGetLastError()
?You could try this in native code to work out the correct inputs first without the additional baggage of P/Invoke.