使用RegQueryValueEx获取可能是REG_DWORD或REG_SZ的注册表值

时间:2017-07-31 23:00:04

标签: c++ windows registry

目前我正在使用RegQueryValueEx()来检索可能以REG_SZREG_DWORD格式编写的注册表值。

BYTE byteArray[MAX];
DWORD dataSize = sizeof(byteArray);
DWORD type = 0;
RegQueryValueEx(
        hKey,
        subKey,
        nullptr,
        &type,
        reinterpret_cast<BYTE*>(&byteArray),
        &dataSize));

当我获得REG_SZ值的数据时(例如:&#34; 42314&#34;),我得到了回复:

byteArray   0x004fe6a8 "4"  unsigned char[100]
    [0] 52 '4'  unsigned char
    [1] 0 '\0'  unsigned char
    [2] 50 '2'  unsigned char
    [3] 0 '\0'  unsigned char
    [4] 51 '3'  unsigned char
    [5] 0 '\0'  unsigned char
    [6] 49 '1'  unsigned char
    [7] 0 '\0'  unsigned char
    [8] 52 '4'  unsigned char
    [9] 0 '\0'  unsigned char
    [10]0 '\0'  unsigned char

有没有办法在每个字符后都没有空字节?我认为这是因为每个角色都要调用RegEnumValue(),但我不确定。

1 个答案:

答案 0 :(得分:1)

您的问题与RegEnumValue()无关。

您的应用正在调用基于TCHAR的{​​{1}},它实际上是一个映射到RegQueryValueEx()(ANSI)或RegQueryValueExA()(Unicode)的预处理器宏,具体取决于是否在编译时定义RegQueryValueExW()

UNICODE将字符串数据作为UTF-16LE格式的Unicode文本返回,这正是您在缓冲区中看到的,所以很明显您的应用程序正在为Unicode编译。你所看到的是完全正常的行为。

因此,您需要以给定的格式处理字符串数据,例如:

RegQueryValueExW()

或者:

BYTE byteArray[MAX];
DWORD dataSize = sizeof(byteArray);
DWORD type = 0;
if (RegQueryValueEx( // <-- calling the TCHAR version!
    hKey,
    subKey,
    nullptr,
    &type,
    reinterpret_cast<BYTE*>(&byteArray),
    &dataSize) == 0)
{
    switch (type)
    {
        case REG_DWORD:
        {
            LPDWORD value = reinterpret_cast<LPDWORD>(&byteArray);
            // use *value as needed ...
            break;
        }

        case REG_SZ:
        case REG_MULTI_SZ:
        case REG_EXPAND_SZ:
        {
            // note the T in LPTSTR!  That means 'TCHAR' is used...
            LPTSTR text = reinterpret_cast<LPTSTR>(&byteArray);
            // use text as needed, up to (dataSize/sizeof(TCHAR)) number
            // of TCHARs. This is because RegQueryValueEx() does not
            // guarantee the output data has a null terminator.  If you
            // want that, use RegGetValue() instead...
            break;
        }
    }
}

如果您想要其他格式的文字,则必须:

  1. 在将其作为Unicode读取后进行转换,例如使用BYTE byteArray[MAX]; DWORD dataSize = sizeof(byteArray); DWORD type = 0; if (RegQueryValueExW( // <-- calling the UNICODE version! hKey, subKey, nullptr, &type, reinterpret_cast<BYTE*>(&byteArray), &dataSize) == 0) { switch (type) { case REG_DWORD: { LPDWORD value = reinterpret_cast<LPDWORD>(&byteArray); // use *value as needed ... break; } case REG_SZ: case REG_MULTI_SZ: case REG_EXPAND_SZ: { // note the W in LPWSTR! That means 'WCHAR' is used... LPWSTR text = reinterpret_cast<LPWSTR>(&byteArray); // use text as needed, up to (dataSize/sizeof(WCHAR)) number // of WCHARs. This is because RegQueryValueExW() does not // guarantee the output data has a null terminator. If you // want that, use RegGetValueW() instead... break; } } } 或等效。

  2. 直接使用WideCharToMultiByte()(或RegQueryValueExA()),根据文档将字符串数据作为ANSI文本返回到用户的当前语言环境中:

      

    如果数据具有RegGetValueA()REG_SZREG_MULTI_SZ类型,则使用此函数的ANSI版本(通过显式调用REG_EXPAND_SZ或未定义在包含RegQueryValueExA文件之前UNICODE,此函数将存储的Unicode字符串转换为ANSI字符串,然后将其复制到Windows.h指向的缓冲区。

    lpData
  3. 无论哪种方式,只需注意您将面临丢失您决定转换为的目标字符集中不存在的任何非ASCII字符的风险。因此,最好坚持使用Unicode,并将缓冲区数据作为BYTE byteArray[MAX]; DWORD dataSize = sizeof(byteArray); DWORD type = 0; if (RegQueryValueExA( // <-- calling the ANSI version hKey, subKey, nullptr, &type, reinterpret_cast<BYTE*>(&byteArray), &dataSize) == 0) { switch (type) { case REG_DWORD: { LPDWORD value = reinterpret_cast<LPDWORD>(&byteArray); // use *value as needed ... break; } case REG_SZ: case REG_MULTI_SZ: case REG_EXPAND_SZ: { // note the lack of T in LPSTR! That means 'char' is used... LPSTR text = reinterpret_cast<LPSTR>(&byteArray); // use text as needed, up to dataSize number of chars. This // is because RegQueryValueExA() does not guarantee the // output data has a null terminator. If you want that, // use RegGetValueA() instead... break; } } } 数据处理(WCHAR在定义TCHAR时映射到的内容。)

相关问题