Перечисление всех подразделов и значений в разделе реестра Windows - PullRequest
4 голосов
/ 26 июля 2011

Я пытаюсь написать приложение для 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 ]

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

Перечислять ключи таким способом излишне. Это будет просто тратить системные ресурсы, память, стек вызовов и оказывать давление на подсистему реестра. Не делайте, если в этом нет необходимости.

Собираетесь ли вы иметь "поиск реестра" в вашем приложении? Если да, перечисляйте только тогда, когда этого требует пользователь. Или, если вы разрабатываете «Просмотр / Редактор реестра», расширяйте и открывайте вложенные ключи только при необходимости.

Если вам абсолютно необходимо получить и сохранить все ключи / значения, вы можете использовать несколько потоков для перечисления ключей. Первоначально количество потоков будет HKEY-major-keys, и тогда вы можете иметь больше потоков, в зависимости от количества вложенных ключей и эвристики времени выполнения, которую вы выполняете при перечислении ключей.

Рекурсия может или не может быть хорошим подходом для "рекурсивного перечисления" подключей - вы должны сохранить минимальное количество аргументов для рекурсивной реализации - поместите аргументы в один struct или поместите их в класс. Вы также можете использовать std::stack для того же.

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

Похоже, что вы вызываете RegEnumValue (), не устанавливая для параметра lpcchValueName правильное значение.Этот параметр является параметром [in], а также параметром [out].Попробуйте это:

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);

Документация для RegEnumValue (): http://msdn.microsoft.com/en-us/library/ms724865(v=vs.85).aspx

...