2011-07-26 63 views
3

我正在嘗試編寫一個Windows應用程序,該應用程序將所有的子項和值給定給某個鍵。我已經編寫了代碼,看起來像在給定的鍵中提供子鍵一樣工作,但不能正確地枚舉值;它成功地枚舉了沒有值的子鍵,並返回結果類型的標籤樹排列。但是,枚舉值時,程序會爲每個存在的值返回一個隨機值(每次都是相同的隨機值),然後在調試錯誤後崩潰。枚舉Windows註冊表項中的所有子項和值

它的目標輸出基本上是:

(1) KEY 
    (1) SUBKEY 
    (1) SUBKEYWITHINSUBKEY 
     Code: value1data 
     Code: value2data 
     Code: value3data 
(2) SUBKEY 
    (1) SUBKEYWITHINSUBKEY 
(3) SUBKEY 

...等等。

我得到的不是輸出是一樣的東西:

(1) KEY 
(1) SUBKEY 
    (1) SUBKEYWITHINSUBKEY 
     Code: someValue 
     Code: someValue 
     Code: someValue 

(...然後崩潰)

在此之後,出現以下錯誤:
「!調試錯誤」運行時檢查失敗#2 - 變量'valNameLen'周圍的堆棧已損壞。「

該代碼目前有點麻煩(我是一個Windows API新手),但如果任何人都可以告訴我我做錯了什麼,或批評我的編碼風格,無論如何,他們覺得合適,這將是偉大的

謝謝!

-R

/* 
Windows Registry Subkey Enumeration Example 
Based on example found at code-blue.org 
*/ 

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

void EnumerateValues(HKEY hKey, DWORD numValues) 
{ 
DWORD dwIndex = 0; 
    LPSTR valueName = new CHAR[64]; 
DWORD valNameLen; 
DWORD dataType; 
DWORD data; 
DWORD dataSize; 

    for (int i = 0; i < numValues; i++) 
{ 
    RegEnumValue(hKey, 
    dwIndex, 
    valueName, 
    &valNameLen, 
    NULL, 
    &dataType, 
    (BYTE*)&data, 
    &dataSize); 

    dwIndex++; 

     printf("Code: 0x%08X\n", data); 
} 
} 


void EnumerateSubKeys(HKEY RootKey, char* subKey, unsigned int tabs = 0) 
{ 
HKEY hKey; 
    DWORD cSubKeys;  //Used to store the number of Subkeys 
    DWORD maxSubkeyLen; //Longest Subkey name length 
    DWORD cValues;  //Used to store the number of Subkeys 
    DWORD maxValueLen; //Longest Subkey name length 
    DWORD retCode;  //Return values of calls 

RegOpenKeyEx(RootKey, subKey, 0, KEY_ALL_ACCESS, &hKey); 

    RegQueryInfoKey(hKey,   // key handle 
        NULL,   // buffer for class name 
        NULL,   // size of class string 
        NULL,   // reserved 
        &cSubKeys,  // number of subkeys 
        &maxSubkeyLen, // longest subkey length 
        NULL,   // longest class string 
        &cValues,  // number of values for this key 
        &maxValueLen, // longest value name 
        NULL,   // longest value data 
        NULL,   // security descriptor 
        NULL);   // last write time 

    if(cSubKeys>0) 
{ 
     char currentSubkey[MAX_PATH]; 

     for(int i=0;i < cSubKeys;i++){ 
    DWORD currentSubLen=MAX_PATH; 

      retCode=RegEnumKeyEx(hKey, // Handle to an open/predefined key 
      i,    // Index of the subkey to retrieve. 
      currentSubkey,   // buffer to receives the name of the subkey 
      &currentSubLen,   // size of that buffer 
      NULL,    // Reserved 
      NULL,    // buffer for class string 
      NULL,    // size of that buffer 
      NULL);    // last write time 

      if(retCode==ERROR_SUCCESS) 
    { 
       for (int i = 0; i < tabs; i++) 
        printf("\t"); 
       printf("(%d) %s\n", i+1, currentSubkey); 

       char* subKeyPath = new char[currentSubLen + strlen(subKey)]; 
       sprintf(subKeyPath, "%s\\%s", subKey, currentSubkey); 
    EnumerateSubKeys(RootKey, subKeyPath, (tabs + 1)); 
    } 
    } 
} 
    else 
{ 
    EnumerateValues(hKey, cValues); 
} 

RegCloseKey(hKey); 
} 


int main() 
{ 
    EnumerateSubKeys(HKEY_CURRENT_USER,"SOFTWARE\\MyKeyToSearchIn"); 
    return 0; 
} 

回答

2

枚舉密鑰這種方式是矯枉過正。這隻會浪費系統資源,內存,調用堆棧並對註冊表子系統施加壓力。除非需要,否則不要做。

你打算在你的應用程序中有「搜索註冊表」嗎?如果是,只有在用戶需要時才列舉。或者,如果您正在開發「註冊表查看器/編輯器」,請僅在需要時展開和打開子密鑰。

如果您絕對需要檢索並存儲所有鍵/值,則可以使用多個線程來枚舉鍵。線程數最初將是HKEY-major-keys,然後可以擁有更多線程,具體取決於您在枚舉鍵時執行的子鍵數和運行時啓發式數。

遞歸可能是也可能不是遞歸枚舉子鍵的好方法 - 您必須保留遞歸實現的最小參數數量 - 將參數放入一個struct或放入類中。您也可以使用std::stack

+0

我重寫了代碼,它完成了我需要的一切。該算法應該沒問題我認爲 - 該實用程序的重點是獲取此信息和其他一些內容,我搜索的密鑰是特定的,並且不包含所有那麼多的子項或值。感謝您的指點! – 8bitcartridge

1

看來,你沒有lpcchValueName參數設置到一個合適的值調用RegEnumValue()。該參數是[in]參數以及[out]參數。試試這個:

爲RegEnumValue()
for (int i = 0; i < numValues; i++) 
 { 
    DWORD valNameLen = 64; //added this line to match valueName buffer size 
  RegEnumValue(hKey, 
     dwIndex, 
     valueName, 
     &valNameLen, 
     NULL, 
     &dataType, 
     (BYTE*)&data, 
     &dataSize); 

文檔:http://msdn.microsoft.com/en-us/library/ms724865(v=vs.85).aspx