2011-12-24 65 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