【问题标题】:Print name, type and data of registry打印登记处名称、类型和数据
【发布时间】:2014-03-02 20:47:55
【问题描述】:

我正在尝试打印有关注册表的信息。我的问题出在第一个 for 循环中。

我无法让它正确打印 dataType 和 data。

另外,将它们添加到同一个打印中会导致程序崩溃或无法正确打印。

#include "stdafx.h"
#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++;

_tprintf(TEXT("(%d) %s %d\n"), i+1, valueName, dataType); 
      // 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\\Dropbox");
   getchar();
    return 0;
}

【问题讨论】:

  • 为什么你不能提供一个完整的程序来演示这个问题?我们看不到任何声明,或者RegTypeToStr 是什么。你可以看到这一切。我们不可以。为什么不?另外,为什么要在 for 循环初始化程序中分配给 retCode ?这是没有意义的,您应该启用编译器警告,以便它可以告诉您它的无用性。
  • 我添加了我正在处理的完整代码。问题出在第一个 for 循环中。我就是做不到。
  • 您添加的代码不包含问题中的原始代码。如果您发布虚假代码,很难提供帮助。你需要对事情有更清晰的把握。你能解释一下为什么你在某些地方使用TEXT 和_tprintf 而不是其他地方。您是为 Unicode 还是 MBCS 编译?看起来很像后者。
  • 多字节。我想先让它工作,然后再处理其余的。

标签: c++ winapi registry


【解决方案1】:

您对RegEnumValue 的呼叫不正确。存在以下问题:

  1. 您需要在调用函数之前初始化valNameLen。
  2. 您需要在调用函数之前初始化dataSize。
  3. 您没有检查RegEnumValue 的返回值,因此假定函数成功。事实上它失败了,因为你上述的错误。

让我们暂时忽略该值,因为它要复杂得多。让我们尝试枚举值的名称。该代码如下所示:

void EnumerateValues(HKEY hKey, DWORD numValues)
{
    for (DWORD dwIndex = 0; dwIndex < numValues; dwIndex++)
    {
        char valueName[64];
        DWORD valNameLen = sizeof(valueName);
        DWORD dataType;
        DWORD dataSize = 0;
        DWORD retval = RegEnumValue(hKey, dwIndex, valueName, &valNameLen,
            NULL, &dataType, NULL, &dataSize);
        if (retval == ERROR_SUCCESS)
        {
            printf("(%d) %s %d\n", dwIndex+1, valueName, dataType);
        }
        else
        {
            // handle error
        }
    }
}

还请注意,我不再像您的代码那样使用动态分配的字符数组。您的代码泄露了该数组。显然,如果您需要处理任意大的值名称,那么您将需要使用动态分配的数组。

至于提取数据,这是一项更大的任务,我不认为它属于 这个问题。每种数据类型都需要特殊代码。

例如,要读取REG_SZ,您可以使用如下代码:

char *data = new char [dataSize+1];
data[dataSize] = '\0';
valNameLen = sizeof(valueName);
DWORD retval = RegEnumValue(hKey, dwIndex, valueName, &valNameLen,
    NULL, NULL, (LPBYTE)data, &dataSize);
if (retval == ERROR_SUCCESS)
{
    printf("(%d) %s %d %s\n", dwIndex+1, valueName, dataType, data);
}
else
{
    // handle error
}
delete[] data;

【讨论】:

  • 如果是 (BYTE*)&data?如何打印 LPBYTE 类型?
  • @user3201639 这取决于数据类型。我想我已经解决了你提出的问题。
  • 只打印名称和类型。但我也需要数据,这给我带来了问题。我应该为此提出另一个问题吗?
  • 问题中的代码没有尝试获取数据。它无法获取值名称和类型。你想让我为你写剩下的程序吗?我已经清除了直接的阻塞。您现在只需要获取数据。至少你可以开始做。很抱歉,您认为这对您没有帮助。
  • 我评论了获取数据的部分,因为它给了我错误,这就是原因。
猜你喜欢
  • 2017-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多