2011-12-24 38 views
4

任务是确定注册表项的最后写入时间。由于标准RegistryKey类不提供此功能,因此我必须使用WinAPI函数“RegQueryInfoKey”。要获得关键句柄,我通过“RegOpenKeyEx”打开它。使用DllImport从C#调用Win API的访问冲突

这是函数的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); 

在这一点上,我得到“访问冲突”的例外。我究竟做错了什么? 我认为参数传递有些问题,但是如何正确执行?

谢谢。

回答

4

原生函数的原型中有5个参数,而P/Invoke签名中只有4个参数。

特别是,你错过了DWORD ulOptions。根据MSDN文档,此参数是“保留并且必须为零”,但它仍然必须在函数调用中传递。

而且,你不需要设置SetLastError field因为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签名几乎总是的“访问冲突”错误的原因。当你看到其中一个时,确保你仔细检查两次!

4

您从P/Invoke签名中错过了ulOptions