C++ 如何从 Windows 注册表中读取值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34065/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to read a value from the Windows registry
提问by nolandda
Given the key for some registry value (e.g. HKEY_LOCAL_MACHINE\blah\blah\blah\foo) how can I:
鉴于某些注册表值的键(例如 HKEY_LOCAL_MACHINE\blah\blah\blah\foo),我该如何:
- Safely determine that such a key exists.
- Programmatically (i.e. with code) get its value.
- 安全地确定存在这样的密钥。
- 以编程方式(即使用代码)获取其值。
I have absolutely no intention of writing anything back to the registry (for the duration of my career if I can help it). So we can skip the lecture about every molecule in my body exploding at the speed of light if I write to the registry incorrectly.
我绝对无意将任何内容写回注册表(如果可以的话,在我的职业生涯中)。因此,如果我错误地写入注册表,我们可以跳过关于我体内每个分子以光速爆炸的讲座。
Prefer answers in C++, but mostly just need to know what the special Windows API incantation to get at the value is.
首选 C++ 中的答案,但大多数情况下只需要知道获得该值的特殊 Windows API 咒语是什么。
采纳答案by Brian R. Bondy
Here is some pseudo-code to retrieve the following:
这是一些伪代码来检索以下内容:
- If a registry key exists
- What the default value is for that registry key
- What a string value is
- What a DWORD value is
- 如果存在注册表项
- 该注册表项的默认值是什么
- 什么是字符串值
- 什么是 DWORD 值
Example code:
示例代码:
Include the library dependency: Advapi32.lib
包含库依赖:Advapi32.lib
HKEY hKey;
LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\Perl", 0, KEY_READ, &hKey);
bool bExistsAndSuccess (lRes == ERROR_SUCCESS);
bool bDoesNotExistsSpecifically (lRes == ERROR_FILE_NOT_FOUND);
std::wstring strValueOfBinDir;
std::wstring strKeyDefaultValue;
GetStringRegKey(hKey, L"BinDir", strValueOfBinDir, L"bad");
GetStringRegKey(hKey, L"", strKeyDefaultValue, L"bad");
LONG GetDWORDRegKey(HKEY hKey, const std::wstring &strValueName, DWORD &nValue, DWORD nDefaultValue)
{
nValue = nDefaultValue;
DWORD dwBufferSize(sizeof(DWORD));
DWORD nResult(0);
LONG nError = ::RegQueryValueExW(hKey,
strValueName.c_str(),
0,
NULL,
reinterpret_cast<LPBYTE>(&nResult),
&dwBufferSize);
if (ERROR_SUCCESS == nError)
{
nValue = nResult;
}
return nError;
}
LONG GetBoolRegKey(HKEY hKey, const std::wstring &strValueName, bool &bValue, bool bDefaultValue)
{
DWORD nDefValue((bDefaultValue) ? 1 : 0);
DWORD nResult(nDefValue);
LONG nError = GetDWORDRegKey(hKey, strValueName.c_str(), nResult, nDefValue);
if (ERROR_SUCCESS == nError)
{
bValue = (nResult != 0) ? true : false;
}
return nError;
}
LONG GetStringRegKey(HKEY hKey, const std::wstring &strValueName, std::wstring &strValue, const std::wstring &strDefaultValue)
{
strValue = strDefaultValue;
WCHAR szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError;
nError = RegQueryValueExW(hKey, strValueName.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (ERROR_SUCCESS == nError)
{
strValue = szBuffer;
}
return nError;
}
回答by Gishu
const CString REG_SW_GROUP_I_WANT = _T("SOFTWARE\My Corporation\My Package\Group I want");
const CString REG_KEY_I_WANT= _T("Key Name");
CRegKey regKey;
DWORD dwValue = 0;
if(ERROR_SUCCESS != regKey.Open(HKEY_LOCAL_MACHINE, REG_SW_GROUP_I_WANT))
{
m_pobLogger->LogError(_T("CRegKey::Open failed in Method"));
regKey.Close();
goto Function_Exit;
}
if( ERROR_SUCCESS != regKey.QueryValue( dwValue, REG_KEY_I_WANT))
{
m_pobLogger->LogError(_T("CRegKey::QueryValue Failed in Method"));
regKey.Close();
goto Function_Exit;
}
// dwValue has the stuff now - use for further processing
回答by Serge
The pair RegOpenKeyand RegQueryKeyExwill do the trick.
RegOpenKey和RegQueryKeyEx对可以解决问题。
If you use MFC CRegKeyclass is even more easier solution.
如果使用 MFC CRegKey类是更简单的解决方案。
回答by Roi Danton
Since Windows >=Vista/Server 2008, RegGetValueis available, which is a safer functionthan RegQueryValueEx. No need for RegOpenKeyEx
, RegCloseKey
or NUL
termination checks of string values (REG_SZ
, REG_MULTI_SZ
, REG_EXPAND_SZ
).
从 Windows >=Vista/Server 2008 开始,可以使用RegGetValue,这是比RegQueryValueEx更安全的功能。无需RegOpenKeyEx
,RegCloseKey
或NUL
字符串值终止检查(REG_SZ
,REG_MULTI_SZ
,REG_EXPAND_SZ
)。
#include <iostream>
#include <string>
#include <exception>
#include <windows.h>
/*! \brief Returns a value from HKLM as string.
\exception std::runtime_error Replace with your error handling.
*/
std::wstring GetStringValueFromHKLM(const std::wstring& regSubKey, const std::wstring& regValue)
{
size_t bufferSize = 0xFFF; // If too small, will be resized down below.
std::wstring valueBuf; // Contiguous buffer since C++11.
valueBuf.resize(bufferSize);
auto cbData = static_cast<DWORD>(bufferSize * sizeof(wchar_t));
auto rc = RegGetValueW(
HKEY_LOCAL_MACHINE,
regSubKey.c_str(),
regValue.c_str(),
RRF_RT_REG_SZ,
nullptr,
static_cast<void*>(valueBuf.data()),
&cbData
);
while (rc == ERROR_MORE_DATA)
{
// Get a buffer that is big enough.
cbData /= sizeof(wchar_t);
if (cbData > static_cast<DWORD>(bufferSize))
{
bufferSize = static_cast<size_t>(cbData);
}
else
{
bufferSize *= 2;
cbData = static_cast<DWORD>(bufferSize * sizeof(wchar_t));
}
valueBuf.resize(bufferSize);
rc = RegGetValueW(
HKEY_LOCAL_MACHINE,
regSubKey.c_str(),
regValue.c_str(),
RRF_RT_REG_SZ,
nullptr,
static_cast<void*>(valueBuf.data()),
&cbData
);
}
if (rc == ERROR_SUCCESS)
{
cbData /= sizeof(wchar_t);
valueBuf.resize(static_cast<size_t>(cbData - 1)); // remove end null character
return valueBuf;
}
else
{
throw std::runtime_error("Windows system error code: " + std::to_string(rc));
}
}
int main()
{
std::wstring regSubKey;
#ifdef _WIN64 // Manually switching between 32bit/64bit for the example. Use dwFlags instead.
regSubKey = L"SOFTWARE\WOW6432Node\Company Name\Application Name\";
#else
regSubKey = L"SOFTWARE\Company Name\Application Name\";
#endif
std::wstring regValue(L"MyValue");
std::wstring valueFromRegistry;
try
{
valueFromRegistry = GetStringValueFromHKLM(regSubKey, regValue);
}
catch (std::exception& e)
{
std::cerr << e.what();
}
std::wcout << valueFromRegistry;
}
Its parameter dwFlags
supports flags for type restriction, filling the value buffer with zeros on failure (RRF_ZEROONFAILURE
) and 32/64bit registry access (RRF_SUBKEY_WOW6464KEY
, RRF_SUBKEY_WOW6432KEY
) for 64bit programs.
它的参数dwFlags
支持类型限制标志,在失败时用零填充值缓冲区 ( RRF_ZEROONFAILURE
) 和 64位程序的32/64 位注册表访问 ( RRF_SUBKEY_WOW6464KEY
, RRF_SUBKEY_WOW6432KEY
)。
回答by Tyler
This gives the value if it exists, and returns an error code ERROR_FILE_NOT_FOUND if the key doesn't exist.
如果存在,则给出值,如果键不存在,则返回错误代码 ERROR_FILE_NOT_FOUND。
(I can't tell if my link is working or not, but if you just google for "RegQueryValueEx" the first hit is the msdn documentation.)
(我不知道我的链接是否有效,但如果你只是在谷歌上搜索“RegQueryValueEx”,第一个命中是 msdn 文档。)
回答by kayleeFrye_onDeck
This console app will list all the values and their data from a registry key for most of the potential registry values. There's some weird ones not often used. If you need to support all of them, expand from this example while referencing this Registry Value Typedocumentation.
此控制台应用程序将列出大多数潜在注册表值的注册表项中的所有值及其数据。有一些不常用的奇怪的。如果您需要支持所有这些,请在参考此注册表值类型文档时从此示例展开。
Let this be the registry key content you can import from a .reg
file format:
让它成为您可以从.reg
文件格式导入的注册表项内容:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\added\subkey]
"String_Value"="hello, world!"
"Binary_Value"=hex:01,01,01,01
"Dword value"=dword:00001224
"QWord val"=hex(b):24,22,12,00,00,00,00,00
"multi-line val"=hex(7):4c,00,69,00,6e,00,65,00,20,00,30,00,00,00,4c,00,69,00,\
6e,00,65,00,20,00,31,00,00,00,4c,00,69,00,6e,00,65,00,20,00,32,00,00,00,00,\
00
"expanded_val"=hex(2):25,00,55,00,53,00,45,00,52,00,50,00,52,00,4f,00,46,00,49,\
00,4c,00,45,00,25,00,5c,00,6e,00,65,00,77,00,5f,00,73,00,74,00,75,00,66,00,\
66,00,00,00
The console app itself:
控制台应用程序本身:
#include <Windows.h>
#include <iostream>
#include <string>
#include <locale>
#include <vector>
#include <iomanip>
int wmain()
{
const auto hKey = HKEY_CURRENT_USER;
constexpr auto lpSubKey = TEXT("added\subkey");
auto openedKey = HKEY();
auto status = RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, &openedKey);
if (status == ERROR_SUCCESS) {
auto valueCount = static_cast<DWORD>(0);
auto maxNameLength = static_cast<DWORD>(0);
auto maxValueLength = static_cast<DWORD>(0);
status = RegQueryInfoKey(openedKey, NULL, NULL, NULL, NULL, NULL, NULL,
&valueCount, &maxNameLength, &maxValueLength, NULL, NULL);
if (status == ERROR_SUCCESS) {
DWORD type = 0;
DWORD index = 0;
std::vector<wchar_t> valueName = std::vector<wchar_t>(maxNameLength + 1);
std::vector<BYTE> dataBuffer = std::vector<BYTE>(maxValueLength);
for (DWORD index = 0; index < valueCount; index++) {
DWORD charCountValueName = static_cast<DWORD>(valueName.size());
DWORD charBytesData = static_cast<DWORD>(dataBuffer.size());
status = RegEnumValue(openedKey, index, valueName.data(), &charCountValueName,
NULL, &type, dataBuffer.data(), &charBytesData);
if (type == REG_SZ) {
const auto reg_string = reinterpret_cast<wchar_t*>(dataBuffer.data());
std::wcout << L"Type: REG_SZ" << std::endl;
std::wcout << L"\tName: " << valueName.data() << std::endl;
std::wcout << L"\tData : " << reg_string << std::endl;
}
else if (type == REG_EXPAND_SZ) {
const auto casted = reinterpret_cast<wchar_t*>(dataBuffer.data());
TCHAR buffer[32000];
ExpandEnvironmentStrings(casted, buffer, 32000);
std::wcout << L"Type: REG_EXPAND_SZ" << std::endl;
std::wcout << L"\tName: " << valueName.data() << std::endl;
std::wcout << L"\tData: " << buffer << std::endl;
}
else if (type == REG_MULTI_SZ) {
std::vector<std::wstring> lines;
const auto str = reinterpret_cast<wchar_t*>(dataBuffer.data());
auto line = str;
lines.emplace_back(line);
for (auto i = 0; i < charBytesData / sizeof(wchar_t) - 1; i++) {
const auto c = str[i];
if (c == 0) {
line = str + i + 1;
const auto new_line = reinterpret_cast<wchar_t*>(line);
if (wcsnlen_s(new_line, 1024) > 0)
lines.emplace_back(new_line);
}
}
std::wcout << L"Type: REG_MULTI_SZ" << std::endl;
std::wcout << L"\tName: " << valueName.data() << std::endl;
std::wcout << L"\tData: " << std::endl;
for (size_t i = 0; i < lines.size(); i++) {
std::wcout << L"\t\tLine[" << i + 1 << L"]: " << lines[i] << std::endl;
}
}
if (type == REG_DWORD) {
const auto dword_value = reinterpret_cast<unsigned long*>(dataBuffer.data());
std::wcout << L"Type: REG_DWORD" << std::endl;
std::wcout << L"\tName: " << valueName.data() << std::endl;
std::wcout << L"\tData : " << std::to_wstring(*dword_value) << std::endl;
}
else if (type == REG_QWORD) {
const auto qword_value = reinterpret_cast<unsigned long long*>(dataBuffer.data());
std::wcout << L"Type: REG_DWORD" << std::endl;
std::wcout << L"\tName: " << valueName.data() << std::endl;
std::wcout << L"\tData : " << std::to_wstring(*qword_value) << std::endl;
}
else if (type == REG_BINARY) {
std::vector<uint16_t> bins;
for (auto i = 0; i < charBytesData; i++) {
bins.push_back(static_cast<uint16_t>(dataBuffer[i]));
}
std::wcout << L"Type: REG_BINARY" << std::endl;
std::wcout << L"\tName: " << valueName.data() << std::endl;
std::wcout << L"\tData:";
for (size_t i = 0; i < bins.size(); i++) {
std::wcout << L" " << std::uppercase << std::hex << \
std::setw(2) << std::setfill(L'0') << std::to_wstring(bins[i]);
}
std::wcout << std::endl;
}
}
}
}
RegCloseKey(openedKey);
return 0;
}
Expected console output:
预期的控制台输出:
Type: REG_SZ
Name: String_Value
Data : hello, world!
Type: REG_BINARY
Name: Binary_Value
Data: 01 01 01 01
Type: REG_DWORD
Name: Dword value
Data : 4644
Type: REG_DWORD
Name: QWord val
Data : 1188388
Type: REG_MULTI_SZ
Name: multi-line val
Data:
Line[1]: Line 0
Line[2]: Line 1
Line[3]: Line 2
Type: REG_EXPAND_SZ
Name: expanded_val
Data: C:\Users\user name\new_stuff
回答by Jarek C
Typically the register key and value are constants in the program. If so, here is an example how to read a DWORD registry value Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled
:
通常,注册键和值是程序中的常量。如果是这样,以下是如何读取 DWORD 注册表值的示例Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled
:
#include <windows.h>
DWORD val;
DWORD dataSize = sizeof(val);
if (ERROR_SUCCESS == RegGetValueA(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\FileSystem", "LongPathsEnabled", RRF_RT_DWORD, nullptr /*type not required*/, &val, &dataSize)) {
printf("Value is %i\n", val);
// no CloseKey needed because it is a predefined registry key
}
else {
printf("Error reading.\n");
}
To adapt for other value types, see https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-reggetvalueafor complete spec.
要适应其他值类型,请参阅https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-reggetvaluea了解完整规范。
回答by Jim Michaels
#include <windows.h>
#include <map>
#include <string>
#include <stdio.h>
#include <string.h>
#include <tr1/stdint.h>
using namespace std;
void printerr(DWORD dwerror) {
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwerror,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
if (isOut) {
fprintf(fout, "%s\n", lpMsgBuf);
} else {
printf("%s\n", lpMsgBuf);
}
// Free the buffer.
LocalFree(lpMsgBuf);
}
bool regreadSZ(string& hkey, string& subkey, string& value, string& returnvalue, string& regValueType) {
char s[128000];
map<string,HKEY> keys;
keys["HKEY_CLASSES_ROOT"]=HKEY_CLASSES_ROOT;
keys["HKEY_CURRENT_CONFIG"]=HKEY_CURRENT_CONFIG; //DID NOT SURVIVE?
keys["HKEY_CURRENT_USER"]=HKEY_CURRENT_USER;
keys["HKEY_LOCAL_MACHINE"]=HKEY_LOCAL_MACHINE;
keys["HKEY_USERS"]=HKEY_USERS;
HKEY mykey;
map<string,DWORD> valuetypes;
valuetypes["REG_SZ"]=REG_SZ;
valuetypes["REG_EXPAND_SZ"]=REG_EXPAND_SZ;
valuetypes["REG_MULTI_SZ"]=REG_MULTI_SZ; //probably can't use this.
LONG retval=RegOpenKeyEx(
keys[hkey], // handle to open key
subkey.c_str(), // subkey name
0, // reserved
KEY_READ, // security access mask
&mykey // handle to open key
);
if (ERROR_SUCCESS != retval) {printerr(retval); return false;}
DWORD slen=128000;
DWORD valuetype = valuetypes[regValueType];
retval=RegQueryValueEx(
mykey, // handle to key
value.c_str(), // value name
NULL, // reserved
(LPDWORD) &valuetype, // type buffer
(LPBYTE)s, // data buffer
(LPDWORD) &slen // size of data buffer
);
switch(retval) {
case ERROR_SUCCESS:
//if (isOut) {
// fprintf(fout,"RegQueryValueEx():ERROR_SUCCESS:succeeded.\n");
//} else {
// printf("RegQueryValueEx():ERROR_SUCCESS:succeeded.\n");
//}
break;
case ERROR_MORE_DATA:
//what do I do now? data buffer is too small.
if (isOut) {
fprintf(fout,"RegQueryValueEx():ERROR_MORE_DATA: need bigger buffer.\n");
} else {
printf("RegQueryValueEx():ERROR_MORE_DATA: need bigger buffer.\n");
}
return false;
case ERROR_FILE_NOT_FOUND:
if (isOut) {
fprintf(fout,"RegQueryValueEx():ERROR_FILE_NOT_FOUND: registry value does not exist.\n");
} else {
printf("RegQueryValueEx():ERROR_FILE_NOT_FOUND: registry value does not exist.\n");
}
return false;
default:
if (isOut) {
fprintf(fout,"RegQueryValueEx():unknown error type 0x%lx.\n", retval);
} else {
printf("RegQueryValueEx():unknown error type 0x%lx.\n", retval);
}
return false;
}
retval=RegCloseKey(mykey);
if (ERROR_SUCCESS != retval) {printerr(retval); return false;}
returnvalue = s;
return true;
}