我创建了一个简单的函数:
std::wstring GetRegKey(const std::string& location, const std::string& name){
const int valueLength = 10240;
auto platformFlag = KEY_WOW64_64KEY;
HKEY key;
TCHAR value[valueLength];
DWORD bufLen = valueLength*sizeof(TCHAR);
long ret;
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, location.c_str(), 0, KEY_READ | platformFlag, &key);
if( ret != ERROR_SUCCESS ){
return std::wstring();
}
ret = RegQueryValueExA(key, name.c_str(), NULL, NULL, (LPBYTE) value, &bufLen);
RegCloseKey(key);
if ( (ret != ERROR_SUCCESS) || (bufLen > valueLength*sizeof(TCHAR)) ){
return std::wstring();
}
std::wstring stringValue(value, (size_t)bufLen - 1);
size_t i = stringValue.length();
while( i > 0 && stringValue[i-1] == '\0' ){
--i;
}
return stringValue;
}
我称之为自动result = GetRegKey("SOFTWARE\\Microsoft\\Cryptography", "MachineGuid");
但字符串看起来像
㤴ㄷ㤵戰㌭㉣ⴱ㔴㍥㤭慣ⴹ㍥摢㘵〴㉡ㄵ\0009ca9-e3bd5640a251
不喜欢RegEdit
4971590b-3c21-45e3-9ca9-e3bd5640a251
所以我想知道如何在C ++中正确表达MachineGuid?
答案 0 :(得分:2)
RegQueryValueExA
是自Windows NT以来Unicode版本的ANSI包装器。在基于Unicode版本的Windows上构建时,它不仅会将lpValueName
转换为LPCWSTR
,还会将从注册表中检索到的lpData
转换为LPWSTR
在回来之前。
MSDN有以下说法:
如果数据具有REG_SZ,REG_MULTI_SZ或REG_EXPAND_SZ类型,则 使用此函数的ANSI版本(通过显式 调用RegQueryValueExA或在包含之前不定义UNICODE 在Windows.h文件中),此函数转换存储的Unicode字符串 在将其复制到指向的缓冲区之前的ANSI字符串 的lpData。
您的问题是,您使用ANSI字符串填充lpData
,其中包含TCHAR
s(在Unicode版本的Windows上为WCHAR
)。
您看到的乱码字符串是2 ANSI char
用于填充单个wchar_t
的结果。这解释了亚洲人物。看起来像GUID结尾的部分是因为打印函数超过了终止null
,因为它只有一个字节并开始打印RegQueryValueExA
所使用的缓冲区的一部分。在转换为ANSI之前。
要解决此问题,要么完全坚持使用Unicode,要么坚持使用ANSI(如果您足够勇于在2014年继续使用ANSI),或者对转换非常谨慎。我会将GetRegKey
更改为接受wstring
并改为使用RegQueryValueExW
,但这是一个偏好问题以及您计划使用此代码的代码类型。
(另外,我建议你有人审查这段代码,因为错误检查有很多奇怪的地方,还有硬编码的缓冲区大小。)