Как получить каждый ключ и подраздел из реестра? - PullRequest
1 голос
/ 27 июля 2011

Я пытаюсь написать приложение, в котором я могу указать путь к реестру, например, HKLM \ hardware \ description \ system и мое приложение должно считывать в системе каждое имя ключа, а также, если есть подразделы, их имя тоже есть больше подразделов, чем их имена, и так далее ...

Мое приложение работает (более или менее), но моя проблема в том, как подсчитать подключи? Например, если в системе есть 2 ключа, a и b, а под a еще 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

Ответы [ 2 ]

2 голосов
/ 28 июля 2011

Первое, что нужно сделать, это избавиться от этих глобалов; они просто усложняют вещи. С рекурсией вы хотите все в стеке. Код ниже решает вашу проблему.

#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); 
              } 
         }
    }*/
}
1 голос
/ 28 июля 2011

Это классическая проблема обхода дерева, и, поскольку вы не знаете, насколько глубоки могут быть вложенные ключи, решение - рекурсия. Разработайте функцию, которая принимает ключ и уровень реестра в качестве входных данных. Он перечисляет подключи этого ключа, и для каждого найденного им подключа он вызывает себя с этим подключом и уровнем + 1 в качестве параметров.

Рекурсия - это сложная концепция, чтобы охватить ваш разум, но как только вы это сделаете, ее элегантность станет прекрасной вещью в подобных ситуациях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...