枚举Windows注册表项中的所有子项和值

8bi*_*dge 5 c++ windows registry enumeration

我正在尝试编写一个Windows应用程序,该应用程序可以为我提供给定特定键的所有子键和值。我编写的代码似乎可以在给定键中提供子键的范围内正常工作,但不能正确枚举值。它成功枚举了没有值的子项,并以选项卡式树的形式返回了结果。但是,在枚举值时,程序会为存在的每个值返回一个随机值(每次都相同的随机值),然后由于调试错误而崩溃。

预期的输出基本上是:

(1) KEY
    (1) SUBKEY
    (1) SUBKEYWITHINSUBKEY
        Code: value1data
        Code: value2data
        Code: value3data
(2) SUBKEY
    (1) SUBKEYWITHINSUBKEY
(3) SUBKEY
Run Code Online (Sandbox Code Playgroud)

...等等。

相反,我得到的输出是这样的:

(1) KEY
(1) SUBKEY
    (1) SUBKEYWITHINSUBKEY
        Code: someValue
        Code: someValue
        Code: someValue
Run Code Online (Sandbox Code Playgroud)

(...然后是崩溃)

,然后出现以下错误:
“调试错误!”运行时检查失败#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;
}
Run Code Online (Sandbox Code Playgroud)

Aja*_*jay 2

以这种方式枚举键是多余的。这只会浪费系统资源、内存、调用堆栈,并对注册表子系统造成压力。除非需要,否则不要做。

您的应用程序中是否有“搜索注册表”?如果是,则仅在用户需要时才进行枚举。或者,如果您正在开发“注册表查看器/编辑器”,请仅在需要时展开和打开子项。

如果您确实需要检索和存储所有键/值,则可以使用多个线程来枚举键。线程的数量最初是 HKEY 主键,然后您可以拥有更多线程,具体取决于子键的数量以及您在枚举键时执行的运行时启发法。

对于子键的“递归枚举”,递归可能是也可能不是好方法 - 您必须将递归实现的参数数量保持在最低限度 - 将参数放入一个struct或将它们放入类中。您可能也想使用std::stack同样的功能。