2011-07-27 6 views
1

J'essaye d'écrire une application, où je peux donner un chemin de registre, tel HKLM \ hardware \ description \ system et mon application devrait lire sous le système chaque nom de clef, et s'il y a des sous-clefs aussi, et s'il y a y a-t-il d'autres sous-clés alors leurs noms aussi et ainsi de suite ...Comment obtenir chaque clé et sous-clé du registre?

Mon application fonctionne (plus ou moins), mais mon problème est de savoir comment compter les sous-clés? Par exemple si sous le système il y a 2 clés, a et b, et sous a il y a 3 clés de plus, et sous b il y en a 5 de plus, alors comment devrais-je compter quel sous-niveau je suis? Ceci est important, car je dois savoir comment concaténer le chemin du registre?

Voici mon code jusqu'à présent (la majeure partie est de msdn, mais je ne peux pas trouver un exemple similaire nulle part):

#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 

Répondre

1

La première chose à faire est de se débarrasser de ces globals; ils ne font que compliquer les choses. Avec la récursivité, vous voulez tout sur la pile. Le code ci-dessous résout votre problème.

#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

Merci beaucoup! Ce code fonctionne comme un charme. Je pense que je dois apprendre un peu plus :) – kampi

1

Ceci est un problème traversal arbre classique et puisque vous ne savoir à quelle profondeur les sous-clés peuvent aller, la solution est la récursivité. Concevoir une fonction qui accepte une clé de registre et un niveau en entrée. Il énumère les sous-clés de cette clé, et pour chaque sous-clé qu'il trouve, il s'appelle lui-même avec cette sous-clé et le niveau + 1 comme paramètres.

La récurrence est un concept difficile à contourner, mais une fois que vous faites, son élégance est une chose de beauté dans des problèmes comme celui-ci.

+0

Salut! Je sais que :) Je ne sais pas comment faire ça. Si vous voyez mon code, alors j'utilise la récursivité, mais il semble que je fasse quelque chose de mal. Que dois-je faire avec le niveau? Pourriez-vous fournir un exemple de code? – kampi

+0

Désolé, j'ai écrémé le code trop rapidement. Ma faute. –

Questions connexes