将 RegQueryValueEx 用于可能是 REG_DWORD 或 REG_SZ 的注册表值
Posted
技术标签:
【中文标题】将 RegQueryValueEx 用于可能是 REG_DWORD 或 REG_SZ 的注册表值【英文标题】:Using RegQueryValueEx for a registry value that could be REG_DWORD or REG_SZ 【发布时间】:2017-07-31 23:00:04 【问题描述】:目前我正在使用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()
,但我不确定。
【问题讨论】:
你在问什么? 它是 Unicode UTF16-LE 以 16bit 0 结尾 【参考方案1】:您的问题与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;
如果您想要其他格式的文本,您必须:
在将其读取为 Unicode 后将其转换为 Unicode,例如使用 WideCharToMultiByte()
或等价的。
根据文档,直接使用RegQueryValueExA()
(或RegGetValueA()
),它将以用户当前语言环境中的ANSI文本形式返回字符串数据:
如果数据具有
REG_SZ
、REG_MULTI_SZ
或REG_EXPAND_SZ
类型,并且使用此函数的ANSI 版本(通过显式调用RegQueryValueExA
或在包含@987654338 之前不定义UNICODE
@file),此函数将存储的 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
定义时的内容)。
【讨论】:
太棒了!我实际上想将它作为 DWORD 存储回来,所以现在我正在将它从LPDWORD value = reinterpret_cast<LPDWORD>(&byteArray);
DWORD output = _ttoi(value);
转换如果有更有效的方法,请告诉我!我对这些类型的转化不太熟悉
您不能将REG_SZ
缓冲区转换为LPDWORD
指针(当然可以,但它没有意义),并且您不能传递LPDWORD
指针到_ttoi()
,因为它需要一个空终止的TCHAR*
指针。并且RegQueryValueEx()
不保证空终止符将出现在输出缓冲区中。因此,请改用RegGetValue()
,然后您可以使用LPTSTR text = reinterpret_cast<LPTSTR>(&byteArray); DWORD value = _ttoi(text);
以上是关于将 RegQueryValueEx 用于可能是 REG_DWORD 或 REG_SZ 的注册表值的主要内容,如果未能解决你的问题,请参考以下文章
使用 RegQueryValueEx 将 reg_sz 作为输入并将其用作 char 数组
RegQueryValueEx 返回 ERROR_SUCCESS 但它没有给我数据缓冲区。为啥?
使用 RegQueryValueEx 和 HKEY_PERFORMANCE_COUNTER 获取“Disk Bytes/sec%