2011-07-27 86 views
1

我想寫一個應用程序,在那裏我可以給一個註冊表路徑,例如HKLM \ hardware \ description \ system,並且我的應用程序應該在系統中讀取每個鍵的名稱,並且如果有子鍵的話,它們的名稱也是如此是更多的子鍵,然後他們的名字也是如此...如何從註冊表中獲取每個密鑰和子項?

我的應用程序工作(或多或少),但我的問題是如何計算子鍵?例如,如果在系統下有2個鍵,a和b,並且在一個下面有3個更多的鍵,並且在b下面還有5個鍵,那麼我應該如何計算我的哪個子級?這很重要,因爲我必須知道如何連接註冊表路徑?

這裏是我到目前爲止的代碼(大部分是從MSDN,但我不能找到無處一個類似的例子):

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

#define MAX_KEY_LENGTH 255 
#define MAX_VALUE_NAME 16383 

void test(wchar_t * OriginalCopy); 
void QueryKey(HKEY hKey, wchar_t * proba); 
void CutLastSubkey(wchar_t * SubKey, int howmuch); 

wchar_t OriginalLocation[] = L"hardware\\description\\system"; 
DWORD Level = 0; 
int counter = 0; 

void __cdecl _tmain(void) 
{ 
    wchar_t OriginalCopy[ 512 ]; 

wcscpy(OriginalCopy, OriginalLocation); 

test(OriginalCopy); 

} 

void test(wchar_t * OriginalCopy) 
{ 
    HKEY hTestKey; 

    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, OriginalCopy, 0, KEY_READ, &hTestKey) == ERROR_SUCCESS) 
    { 
     //printf("\n%ls",OriginalCopy); 
     QueryKey(hTestKey, OriginalCopy); 
    } 
    else printf("\nTest Failed"); 
    RegCloseKey(hTestKey); 

} 

void QueryKey(HKEY hKey, wchar_t * OriginalCopy) 
{ 
printf("\n1. OriginalCopy: %ls Level %d", OriginalCopy, Level); 

TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name 
DWORD cbName;     // size of name string 
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name 
DWORD cchClassName = MAX_PATH; // size of class string 
DWORD cSubKeys=0;    // number of subkeys 
DWORD cbMaxSubKey;    // longest subkey size 
DWORD cchMaxClass;    // longest class string 
DWORD cValues;    // number of values for key 
DWORD cchMaxValue;   // longest value name 
DWORD cbMaxValueData;  // longest value data 
DWORD cbSecurityDescriptor; // size of security descriptor 
FILETIME ftLastWriteTime;  // last write time 

DWORD i, retCode; 

TCHAR achValue[MAX_VALUE_NAME]; 
DWORD cchValue = MAX_VALUE_NAME; 

// Get the class name and the value count. 
retCode = RegQueryInfoKey(
    hKey,     // key handle 
    achClass,    // buffer for class name 
    &cchClassName,   // size of class string 
    NULL,     // reserved 
    &cSubKeys,    // number of subkeys 
    &cbMaxSubKey,   // longest subkey size 
    &cchMaxClass,   // longest class string 
    &cValues,    // number of values for this key 
    &cchMaxValue,   // longest value name 
    &cbMaxValueData,   // longest value data 
    &cbSecurityDescriptor, // security descriptor 
    &ftLastWriteTime);  // last write time 

// Enumerate the subkeys, until RegEnumKeyEx fails. 

if (cSubKeys) 
{ 
    printf("\nNumber of subkeys: %d\n", cSubKeys); 

    for (i=0; i<cSubKeys; i++) 
    { 
     cbName = MAX_KEY_LENGTH; 
     retCode = RegEnumKeyExW(hKey, 
           i, 
           achKey, 
           &cbName, 
           NULL, 
           NULL, 
           NULL, 
           &ftLastWriteTime 
          ); 

     if (retCode == ERROR_SUCCESS) 
     { 
      //_tprintf(TEXT("(%d) %s\n"), i+1, achKey); 
      //------------------------------------------------------------------- 
      HKEY subkey; 

      Level++; 
      wcscat(OriginalCopy, L"\\"); 
      wcscat(OriginalCopy, achKey); 
      printf("\nNew subkey found \"%ls\" Number of subkeys: %d\n",achKey, cSubKeys); 
      printf("\nNew OriginalCopy \"%ls\"Level: %d\n", OriginalCopy, Level); 

      if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, OriginalCopy, 0, KEY_READ, &subkey) == ERROR_SUCCESS) 
      {    
       counter++; 
       test(OriginalCopy); 
       RegCloseKey(subkey); 
      } 
      else printf("\n-----Querykey Failed for %ls\n",OriginalCopy); 


      //------------------------------------------------------------------- 
     } 
    } 
} 
else 
{ 
    Level--; 
    printf("\nNo subkeys \"%ls\" Level : %d Counter %d",OriginalCopy, Level, counter); 
    CutLastSubkey(OriginalCopy, 1); 

    //counter--; 
} 

// Enumerate the key values. 

/*if (cValues) 
{ 
    printf("\nNumber of values: %d\n", cValues); 

    for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) 
    { 
     cchValue = MAX_VALUE_NAME; 
     achValue[0] = '\0'; 
     retCode = RegEnumValue(hKey, 
           i, 
           achValue, 
           &cchValue, 
           NULL, 
           NULL, 
           NULL, 
           NULL 
          ); 

     if (retCode == ERROR_SUCCESS) 
     { 
      _tprintf(TEXT("(%d) %s\n"), i+1, achValue); 
     } 
    } 
}*/ 
} 

void CutLastSubkey(wchar_t * SubKey, int howmuch) 
{ 
wchar_t * pch, tmp[ 1024 ] = { 0 }; 
int location, i; 

printf("\n\nCutlast was called with %d", howmuch); 
pch = wcsrchr(SubKey,'\\');//last occurence of \ in string 
location = pch - SubKey + 1; 
//printf("Last occurence of '\\' found at %d in %ls \n",location, SubKey); 
location--; 

SubKey[ location ] = '\0'; 

printf("\n+++CutLastSubkey result :: \"%ls\"", SubKey); 
if (howmuch > 1) 
{ 
    CutLastSubkey(SubKey, Level -1); 
} 

}//CutLastSubkey 

回答

1

要做的第一件事就是擺脫這些全局變量;他們只是複雜的事情。通過遞歸,你需要堆棧中的所有東西。下面的代碼解決了你的問題。

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

#define MAX_KEY_LENGTH 255 
#define MAX_VALUE_NAME 16383 

void test(wchar_t * OriginalCopy, DWORD Level); 
void QueryKey(HKEY hKey, const wchar_t * proba, DWORD Level); 


int counter = 0; 

void __cdecl _tmain(void) 
{ 

    test(L"hardware\\description\\system", 0); 

} 

void test(wchar_t * OriginalCopy, DWORD Level) 
{ 
    HKEY hTestKey; 

    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCWSTR)OriginalCopy, 0, KEY_READ, &hTestKey) == ERROR_SUCCESS) 
    { 
     //printf("\n%ls",OriginalCopy); 
     QueryKey(hTestKey, OriginalCopy, Level); 
    } 
    else printf("\nTest Failed"); 
    RegCloseKey(hTestKey); 

} 

void QueryKey(HKEY hKey, const wchar_t * OriginalCopy, DWORD Level) 
{ 
    //printf("\n1. OriginalCopy: %ls Level %d", OriginalCopy, Level); 

    TCHAR achKey[MAX_KEY_LENGTH];  // buffer for subkey name 
    DWORD cbName;       // size of name string 
    TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name 
    DWORD cchClassName = MAX_PATH; // size of class string 
    DWORD cSubKeys=0;      // number of subkeys 
    DWORD cbMaxSubKey;     // longest subkey size 
    DWORD cchMaxClass;     // longest class string 
    DWORD cValues;     // number of values for key 
    DWORD cchMaxValue;   // longest value name 
    DWORD cbMaxValueData;   // longest value data 
    DWORD cbSecurityDescriptor; // size of security descriptor 
    FILETIME ftLastWriteTime;  // last write time 

    DWORD i, retCode; 

    DWORD cchValue = MAX_VALUE_NAME; 

    // Get the class name and the value count. 
    retCode = RegQueryInfoKey(
            hKey,      // key handle 
            achClass,     // buffer for class name 
            &cchClassName,   // size of class string 
            NULL,      // reserved 
            &cSubKeys,     // number of subkeys 
            &cbMaxSubKey,    // longest subkey size 
            &cchMaxClass,    // longest class string 
            &cValues,     // number of values for this key 
            &cchMaxValue,    // longest value name 
            &cbMaxValueData,    // longest value data 
            &cbSecurityDescriptor, // security descriptor 
            &ftLastWriteTime);  // last write time 

    // Enumerate the subkeys, until RegEnumKeyEx fails. 

    if (cSubKeys) 
    { 
     //printf("\nNumber of subkeys: %d\n", cSubKeys); 

     for (i=0; i<cSubKeys; i++) 
     { 
      cbName = MAX_KEY_LENGTH; 
      retCode = RegEnumKeyExW(hKey, 
              i, 
              (LPWSTR)achKey, 
              &cbName, 
              NULL, 
              NULL, 
              NULL, 
              &ftLastWriteTime 
             ); 

      if (retCode == ERROR_SUCCESS) 
      { 
       //_tprintf(TEXT("(%d) %s\n"), i+1, achKey); 
       //------------------------------------------------------------------- 
       HKEY subkey; 

       wchar_t NewCopy[MAX_PATH]; 
       wcscpy(NewCopy, OriginalCopy); 
       wcscat(NewCopy, L"\\"); 
       wcscat(NewCopy, (const wchar_t *)achKey); 
       //printf("\nNew subkey found \"%ls\" Number of subkeys: %d\n",achKey, cSubKeys); 
       printf("\nNew OriginalCopy \"%ls\"Level: %d\n", NewCopy, Level); 

       if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, OriginalCopy, 0, KEY_READ, &subkey) == ERROR_SUCCESS) 
       { 
        counter++; 
        test(NewCopy, Level+1); 
        RegCloseKey(subkey); 
       } 
       else printf("\n-----Querykey Failed for %ls\n",OriginalCopy); 


       //------------------------------------------------------------------- 
      } 
     } 
    } 

    // Enumerate the key values. 

    /*if (cValues) 
    { 
     printf("\nNumber of values: %d\n", cValues); 

     for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) 
     { 
       cchValue = MAX_VALUE_NAME; 
       achValue[0] = '\0'; 
       retCode = RegEnumValue(hKey, 
               i, 
               achValue, 
               &cchValue, 
               NULL, 
               NULL, 
               NULL, 
               NULL 
              ); 

       if (retCode == ERROR_SUCCESS) 
       { 
        _tprintf(TEXT("(%d) %s\n"), i+1, achValue); 
       } 
     } 
    }*/ 
} 
+0

非常感謝!這段代碼就像一個魅力。我想我必須學習更多一點:) – kampi

1

這是一個典型的樹的遍歷問題,因爲你不知道子密鑰可能有多深,解決方案是遞歸。設計一個接受註冊表項和級別作爲輸入的函數。它枚舉該鍵的子鍵,並且找到它找到的每個子鍵,都會使用該子鍵和level + 1作爲參數來調用它自己。

遞歸是一個困難的概念來包裹你的思想,但一旦你做到了,它的優雅是這樣的問題美的東西。

+0

嗨!我知道:)我只是不知道該怎麼做。如果你看到我的代碼,那麼我使用遞歸,但似乎我做錯了什麼。我應該如何處理關卡?你可以提供一些示例代碼? – kampi

+0

對不起,我太快地瀏覽了代碼。我的錯。 –