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

问题描述 投票:0回答:2

目前我正在使用

RegQueryValueEx()
检索可能以
REG_SZ
REG_DWORD
格式写入的注册表值。

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

当我获取

REG_SZ
值的数据(例如:“42314”)时,我得到以下响应:

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()
,但我不确定。

c++ windows registry
2个回答
2
投票

您的问题与

RegEnumValue()
无关。

您的应用程序正在调用基于

TCHAR
RegQueryValueEx()
,它实际上是一个预处理器宏,映射到
RegQueryValueExA()
(ANSI) 或
RegQueryValueExW()
(Unicode),具体取决于
UNICODE
是否在编译时定义 -时间。

RegQueryValueExW()
以 UTF-16LE 格式将字符串数据返回为 Unicode 文本,这正是您在缓冲区中看到的内容,因此显然您的应用程序正在针对 Unicode 进行编译。您所看到的是完全正常的行为。

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

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

或者:

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

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

  1. 将其读取为 Unicode 后将其转换,例如使用

    WideCharToMultiByte()
    或等效的。

  2. 直接使用

    RegQueryValueExA()
    (或
    RegGetValueA()
    ),根据文档,这将返回用户当前语言环境中的 ANSI 文本字符串数据:

    如果数据具有

    REG_SZ
    REG_MULTI_SZ
    REG_EXPAND_SZ
    类型,并且使用此函数的 ANSI 版本(通过显式调用
    RegQueryValueExA
    或在包含
    UNICODE
    文件之前不定义
    Windows.h
    ) ),该函数将存储的 Unicode 字符串转换为 ANSI 字符串,然后将其复制到
    lpData
    指向的缓冲区。

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

无论哪种方式,请注意,您将面临丢失您决定转换的目标字符集中不存在的任何非 ASCII 字符的风险。因此,最好坚持使用 Unicode,并将缓冲区数据处理为

WCHAR
数据(定义
TCHAR
UNICODE
映射到什么)。


0
投票
Example showing opening/creating key, setting value, and finally querying it.
#include "stdafx.h"
#include <atlbase.h>

void MessageIDs_RegistryAdd() {
  LONG nError = 0;
  HKEY ROOT_KEY = HKEY_CURRENT_USER;
  HKEY hOpenKey = 0;
  char *strKey = "Software\\AKey\\AnotherKey";

  // Open Key
  nError = RegOpenKeyEx( ROOT_KEY, strKey, NULL, KEY_ALL_ACCESS, &hOpenKey );
  if (nError == ERROR_FILE_NOT_FOUND) {
    // Create Key
    nError = RegCreateKeyEx( ROOT_KEY, strKey, NULL, NULL, REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS, NULL, &hOpenKey, NULL);
    }
  if ( nError != ERROR_SUCCESS ) {
    OutputDebugString("  Error opening/creating key\r\n");
    return;
    } 

  // Set Key Value
  DWORD dwValue = 42;
  nError = RegSetValueEx( hOpenKey, NULL, 0, REG_DWORD, (const BYTE*)&dwValue, sizeof(dwValue) );
  if ( nError != ERROR_SUCCESS ) {
    OutputDebugString("  Error setting key value\r\n");
    return;
    }

  // Read Key
  const int MAX = 4096;
  DWORD type = REG_DWORD;
  DWORD dataSize = sizeof(DWORD);
  DWORD theVal = 0;
  nError = RegQueryValueEx( hOpenKey, NULL, nullptr, &type, reinterpret_cast<BYTE*>(&theVal), &dataSize );
  if ( nError != ERROR_SUCCESS ) {
    OutputDebugString("  Error reading key value\r\n");
    return;
    }

  // Close key
  nError = RegCloseKey( hOpenKey );
  if ( nError != ERROR_SUCCESS ) {
    OutputDebugString("  Error closing key.");
    return;
    }

  return;
  }

// Darryl Bassett
© www.soinside.com 2019 - 2024. All rights reserved.