windows 对注册表值使用RegQueryValueEx,注册表值可以是REG_DWORD或REG_SZ

new9mtju  于 2023-10-22  发布在  Windows
关注(0)|答案(2)|浏览(118)

目前我使用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值的数据时(例如:“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()被调用为每个字符,但我不确定。

px9o7tmv

px9o7tmv1#

您的问题与RegEnumValue()无关。
您的应用正在调用基于TCHARRegQueryValueEx(),这实际上是一个预处理器宏,它Map到RegQueryValueExA()(ANSI)或RegQueryValueExW()(Unicode),具体取决于UNICODE是否在编译时定义。
RegQueryValueExW()以UTF-16 LE格式的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后将其转换为Unicode,例如使用WideCharToMultiByte()或等效项。
1.直接使用RegQueryValueExA()(或RegGetValueA()),这将返回用户当前区域设置中的ANSI文本形式的字符串数据,根据文档:
如果数据类型为REG_SZREG_MULTI_SZREG_EXPAND_SZ,并且使用了此函数的ANSI版本(通过显式调用RegQueryValueExA或在包含Windows.h文件之前不定义UNICODE),则此函数将存储的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数据处理(当定义UNICODE时,TCHARMap到的数据)。

w8rqjzmb

w8rqjzmb2#

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

相关问题