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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6825555/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 17:35:47  来源:igfitidea点击:

Enumerating all subkeys and values in a Windows registry key

c++windowsregistryenumeration

提问by 8bitcartridge

I am trying to write a Windows application that gives me back all the subkeys and values given a certain key. I've written code that appears to work as far as providing subkeys within the given key, but doesn't work at properly enumerating the values; it successfully enumerates subkeys without values and returns the results in kind of tabbed tree arrangement. However, when enumerating values, the program gives back a random value for each value present (the same random value each time), and then crashes afterwards with a debug error.

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

It's intended output is basically:

它的预期输出基本上是:

(1) KEY
    (1) SUBKEY
    (1) SUBKEYWITHINSUBKEY
        Code: value1data
        Code: value2data
        Code: value3data
(2) SUBKEY
    (1) SUBKEYWITHINSUBKEY
(3) SUBKEY

...and so on.

...等等。

The output I get instead is something like:

我得到的输出是这样的:

(1) KEY
(1) SUBKEY
    (1) SUBKEYWITHINSUBKEY
        Code: someValue
        Code: someValue
        Code: someValue

(...and then the crash)

This is followed with the following error:
"Debug Error! "Run-Time Check Failure #2 - Stack around the variable 'valNameLen' was corrupted."

(...然后是崩溃)

随后出现以下错误:
“调试错误!”运行时检查失败 #2 - 变量 'valNameLen' 周围的堆栈已损坏。

The code is a bit messy currently (I'm a Windows API newbie), but if anyone could show me what I'm doing wrong, or critique my coding style in anyway they feel fit, that would be great.

代码目前有点乱(我是 Windows API 新手),但是如果有人能告诉我我做错了什么,或者以他们认为合适的方式批评我的编码风格,那就太好了。

Thanks!

谢谢!

-R

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

采纳答案by Ajay

Enumerating the keys this way is overkill. This would simply waste the system resources, memory, call-stack and put pressure on registry sub-system. Do not do unless needed.

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

Are you going to have "search registry" in your application? If yes, enumerate only when user demands so. Or, if you are developing "Registry Viewer/Editor", do expand and open sub-keys only when needed.

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

If you absolutely need to retrieve and store all keys/values, you can use multiple threads to enumerate the keys. The number of threads would initially be the HKEY-major-keys, and then you can have more threads, depending on number of sub keys and runtime heuristics you perform while enumerating the keys.

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

Recursion may or may not be good approach for "recursive-enumeration" of sub-keys - you must keep number of arguments to recursive implementation minimum - put the arguments into one structor put them in class. You may also like to use std::stackfor the same.

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

回答by Brain2000

It appears that you are calling RegEnumValue() without setting the lpcchValueName parameter to a proper value. This parameter is an [in] parameter as well as an [out] parameter. Try this:

您似乎在调用 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);

Documentation for RegEnumValue() : http://msdn.microsoft.com/en-us/library/ms724865(v=vs.85).aspx

RegEnumValue() 的文档:http: //msdn.microsoft.com/en-us/library/ms724865(v=vs.85) .aspx

回答by Phani Rithvij

I tried your code on a key with a very small number of subkeys.

我在一个子键数量很少的键上尝试了你的代码。

In the function EnumerateValuesafter calling RegEnumValueonce, the value of numValuesis getting filled with some random junk. The solution is to change the parameters of RegEnumValueto

EnumerateValues调用RegEnumValue一次后的函数中, 的值numValues被一些随机的垃圾填满。解决办法是修改参数RegEnumValue

    RegEnumValueA(hKey,
               dwIndex,
               valueName,
               &valNameLen,
               nullptr,
               nullptr,
               nullptr,
               nullptr);

This is the function finally,

最后就是这个功能了

void EnumerateValues(HKEY hKey, DWORD numValues)
{
    DWORD dwIndex = 0;
    LPSTR valueName = new CHAR[64];
    DWORD valNameLen;

    DWORD numback = numValues;

    for (int i = 0; i < numValues; i++)
    {
        // printf("%lu, %d\n", numValues, i);
        RegEnumValueA(hKey,
                      dwIndex,
                      valueName,
                      &valNameLen,
                      nullptr,
                      nullptr,
                      nullptr,
                      nullptr);

        dwIndex++;

        if (i > numback)
        {
            RegCloseKey(hKey);
            printf("Inf loop exiting...\n");
            exit(-1);
        }

        // printf("Code: 0x%08X, %lu, %d\n", data, numValues, i);
        // printf("Code: %lu, %d\n", numValues, i);
    }
    RegCloseKey(hKey);
}