2014-05-02 144 views
0

我嘗試閱讀我的NPAPI-插件註冊表:C++讀取註冊表

bool ScriptablePluginObject::Invoke(NPObject* obj, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result) { 
    ScriptablePluginObject *thisObj = (ScriptablePluginObject*) obj; 
    char* name      = npnfuncs->utf8fromidentifier(methodName); 
    LPCWSTR game_path    = getRegKey(L"SOFTWARE\\World of RPG", L"Path"); 

    MessageBox(NULL, game_path, L"Debugging", MB_TOPMOST); 

    /* ... */ 
} 

LPCWSTR ScriptablePluginObject::getRegKey(LPCWSTR location, LPCWSTR name) { 
    HKEY hKey; 
    LPBYTE folder = new BYTE[MAX_PATH]; 
    DWORD dwSize = sizeof(folder); 
    long registry = RegOpenKeyEx(HKEY_LOCAL_MACHINE, location, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); 
    long entry  = RegQueryValueEx(hKey, name, NULL, REG_NONE, folder, &dwSize); 

    if(registry != ERROR_SUCCESS) { 
     return L"Error1"; 
    } 

    if(entry != ERROR_SUCCESS) { 
     return L"Error2"; 
    } 

    RegCloseKey(hKey); 
    folder[dwSize/sizeof(folder[0])] = '\0'; 
    return (LPCWSTR) folder; 
} 

但它返回的每一個電話Error2。我已經嘗試了很多變化:

  • 改變路徑(以開始和/或結束\\
  • 變化參數

我想要得到的HKEY_LOCAL_MACHINE\SOFTWARE\World of RPG\Path路徑:

enter image description here

任何人都可以幫到我嗎?我做錯了什麼?

+1

嘗試檢查實際[返回值](http://msdn.microsoft.com/en-us/庫/風ows/desktop/ms724897%28v = vs.85%29.aspx),看看它爲什麼失敗。如果你沒有檢查返回值,你看不到爲什麼它不返回'ERROR_SUCCESS'。它返回其他的值,這些值有意義,但是如果你真的看看它的含義,它的意義就很重要。你寫的代碼現在寫道:「如果它不能成功,給我看一些ErrorX的無意義文本。」相反,保存返回值,並檢查保存的值是否符合'ERROR_SUCCESS'。 –

+0

我真的是新的C++。我試圖將長整型值轉換爲LPCWSTR以在消息框中打印出來。但它不起作用:http://pastebin.com/1Q2F3JMp –

+0

將數字轉換爲字符串是一項非常標準的任務,並且與Windows API或註冊表無關。如果你不能執行這個任務,也許你還沒有準備好嘗試編寫一個NPAPI插件。請參閱[這裏](http://www.cplusplus.com/articles/D9j2Nwbp/)瞭解如何進行轉換 - 我發現它在Google中使用'cplusplus integer to string'。 –

回答

2

getRegKey(),您的folder變量是一個指針,所以sizeof(folder)是4(如果編譯爲32位)或8(如果編譯爲64位)。因此RegQueryValueEx()失敗,並顯示ERROR_MORE_DATA錯誤代碼。

您也正在使用數組的錯誤數據類型。您需要使用WCHAR而不是​​。

更改此:

LPBYTE folder = new BYTE[MAX_PATH]; 
DWORD dwSize = sizeof(folder); 

要這樣:

LPWSTR folder = new WCHAR[MAX_PATH]; 
DWORD dwSize = sizeof(WCHAR) * MAX_PATH; 

雖這麼說,你是泄漏內存folder指出,因爲你永遠不delete[]它。

+0

太棒了!好的,看到問題。如果你只使用像Java或PHP這樣的小語言,C++對新手來說很難:) –

2

這是我在上面提到的意見樣本:

#include <stdlib.h> 
#include <stdio.h> 
#include <tchar.h> 
#include <windows.h> 

LSTATUS ReadRegistry (LPCWSTR sPath, LPCWSTR sKey, LPWSTR pBuffer, DWORD *pBufferSize); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    const int BUFFER_SIZE = 1024; 

    WCHAR sBuffer[BUFFER_SIZE]; // 2048 bytes 
    DWORD nBufferSize = BUFFER_SIZE * sizeof (WCHAR); 

    ZeroMemory (sBuffer, nBufferSize); 
    LSTATUS nResult = ReadRegistry (L"SOFTWARE\\7-Zip", L"Path64", 
     sBuffer, &nBufferSize); 

    // check nResult for ERROR_SUCCESS to know if the call succeeded or not 

    return 0; 
} 

LSTATUS ReadRegistry (LPCWSTR sPath, LPCWSTR sKey, LPWSTR pBuffer, LPDWORD pBufferSize) 
{ 
    HKEY hKey; 
    LSTATUS nResult = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE, sPath, 
     0, KEY_READ | KEY_WOW64_64KEY, &hKey); 

    if (nResult == ERROR_SUCCESS) 
    { 
     nResult = ::RegQueryValueEx (hKey, sKey, NULL, NULL, 
      (LPBYTE) pBuffer, pBufferSize); 

     RegCloseKey (hKey); 
    } 

    return (nResult); 
} 

注意如何ReadRegistry功能不分配內存 - 它需要一個緩衝和數據填充它。如果你總是讓調用者分配內存,處理內存會容易得多。如果被調用者分配內存,調用者可能不知道如何分配內存,並且可能不知道如何釋放內存。 (當然,你總是可以假設使用newdelete,但是事情比較簡單,如果只有一方這樣做是一致的話,如果調用者分配內存,它就知道如何釋放它,被調用者只需要把數據放入分配空間

此外,請注意在繼續下一次調用之前API函數的返回值是如何檢查的 - 這很重要,因爲這會告訴您是否有有用的註冊表句柄,以及是否需要關閉與否。

(此示例是真的只是C,而不是C++,但它仍然適用。)