任务是确定注册表项的最后写入时间。由于标准的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);
在这一点上,我得到"访问冲突"异常。我做错了什么?我认为有些东西是错误的参数传递,但如何做到这一点?
谢谢。
在原生函数的原型中有5个参数,而在你的p/Invoke签名中只有4个。
特别是,你缺少了DWORD ulOptions
。根据MSDN文档,该参数为"保留且必须为零",但它仍然必须在函数调用中传递。
同样,您不需要设置SetLastError
字段,因为RegOpenKeyEx
函数返回其错误码;您不必通过调用GetLastError
来检索它。因此,您不需要封送程序自动为您保存该值。只需检查返回值中的错误代码。
把你的p/Invoke签名改成这样:
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int RegOpenKeyEx(UIntPtr hkey, string lpSubKey,
uint ulOptions, uint samDesired,
out UIntPtr phkResult);
错误的p/Invoke签名几乎总是导致"访问冲突"错误。当你看到其中一个时,一定要仔细检查两次!
您的p/Invoke签名中缺少ulOptions
。