使用 DllImport 从 C# 调用 Win API 时发生访问冲突
任务是确定注册表项的最后写入时间。由于标准RegistryKey类不提供此功能,我必须使用WinAPI函数“RegQueryInfoKey”。为了获取密钥句柄,我通过“RegOpenKeyEx”打开它。
这是该函数的 WinAPI 原型(取自 MSDN):
LONG WINAPI RegOpenKeyEx(
__in HKEY hKey,
__in LPCTSTR lpSubKey,
DWORD ulOptions,
__in REGSAM samDesired,
__out PHKEY phkResult
);
我使用以下声明:
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int RegOpenKeyEx(UIntPtr hkey, string lpSubKey, uint samDesired, ref UIntPtr phkResult);
然后我按以下方式调用它:
UIntPtr hKey = UIntPtr.Zero;
string myKeyName = "blablabla";
UIntPtr HKEY_USERS = (UIntPtr)0x80000003;
uint KEY_READ = 0x20019;
RegOpenKeyEx(HKEY_USERS, myKeyName, KEY_READ, ref hKey);
此时我得到“访问冲突”异常。我做错了什么? 我认为参数传递有问题,但是如何正确处理呢?
谢谢。
The task is to determine the last write time for the registry key. As standard RegistryKey class doesn't provide this feature, I have to use WinAPI function "RegQueryInfoKey". To get the key handle I open it by "RegOpenKeyEx".
This is the WinAPI prototype of the function (taken from MSDN):
LONG WINAPI RegOpenKeyEx(
__in HKEY hKey,
__in LPCTSTR lpSubKey,
DWORD ulOptions,
__in REGSAM samDesired,
__out PHKEY phkResult
);
I use the following declaration:
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int RegOpenKeyEx(UIntPtr hkey, string lpSubKey, uint samDesired, ref UIntPtr phkResult);
Then I call it in the following way:
UIntPtr hKey = UIntPtr.Zero;
string myKeyName = "blablabla";
UIntPtr HKEY_USERS = (UIntPtr)0x80000003;
uint KEY_READ = 0x20019;
RegOpenKeyEx(HKEY_USERS, myKeyName, KEY_READ, ref hKey);
At this point I get "Access violation" exception. What am I doing wrong?
I think something is wrong with parameters passing, but how to do it right?
Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
本机函数的原型中有 5 个参数,而 P/Invoke 签名中只有 4 个参数。
特别是,您缺少
DWORD ulOptions
。根据 MSDN 文档,该参数是“保留的且必须为零”,但仍必须在函数调用中传递。另外,您不需要设置 < code>SetLastError 字段,因为
RegOpenKeyEx
函数返回其错误代码;您不必通过调用GetLastError
来检索它。因此,您不需要封送拆收器自动为您保存该值。只需检查返回值中的错误代码即可。将 P/Invoke 签名更改为如下所示:
错误的 P/Invoke 签名几乎总是导致“访问冲突”错误。当您看到其中之一时,请务必仔细检查两次!
There are 5 parameters in the native function's prototype, and only 4 in your P/Invoke signature.
In particular, you're missing
DWORD ulOptions
. This parameter is "reserved and must be zero" according to the MSDN documentation, but it must still be passed in the function call.Also, you don't need to set the
SetLastError
field because theRegOpenKeyEx
function returns its error code; you don't have to retrieve it by callingGetLastError
. Consequently, you don't need the marshaler to save that value for you automatically. Just check the return value for the error code.Change your P/Invoke signature to look like this:
The wrong P/Invoke signature is almost always the cause of "access violation" errors. When you see one of those, make sure you double-check it twice!
您的 P/Invoke 签名中缺少
ulOptions
。You've missed
ulOptions
from your P/Invoke signature.