Вот какой-то псевдокод для получения следующего:
- Если ключ реестра существует
- Какое значение по умолчанию для этого раздела реестра
- Что такое строковое значение
- Что такое значение DWORD
Пример кода:
Включите зависимость библиотеки: 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;
}
RegOpenKeyExW
иRegQueryValueExW
их агностический эквивалент по «набору символов»RegOpenKeyEx
иRegQueryValueEx
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
источник
CRegKey
звучит как страна ATL или MFC.Начиная с 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; }
Его параметр
dwFlags
поддерживает флаги для ограничения типа, заполнение буфера значений нулями при сбое (RRF_ZEROONFAILURE
) и доступ к 32/64-битному реестру (RRF_SUBKEY_WOW6464KEY
,RRF_SUBKEY_WOW6432KEY
) для 64-битных программ.источник
Пара RegOpenKey и RegQueryKeyEx сделает свое дело.
Если вы используете класс MFC CRegKey, это еще более простое решение.
источник
RegQueryValueEx
Это дает значение, если оно существует, и возвращает код ошибки ERROR_FILE_NOT_FOUND, если ключ не существует.
(Я не могу сказать, работает моя ссылка или нет, но если вы просто погуглите "RegQueryValueEx", первое попадание - это документация msdn.)
источник
Это консольное приложение будет перечислять все значения и их данные из раздела реестра для большинства возможных значений реестра. Есть некоторые странные, которые не часто используются. Если вам нужно поддерживать все из них, разверните этот пример, ссылаясь на этот тип значения реестра. документации по .
Пусть это будет содержимое раздела реестра, которое вы можете импортировать из
.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
Само консольное приложение:
#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; }
Ожидаемый вывод консоли:
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
источник
Обычно ключ и значение регистра в программе являются константами. Если да, то вот пример того, как прочитать значение реестра 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"); }
Чтобы адаптироваться к другим типам значений, см. Https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-reggetvaluea для получения полной спецификации.
источник
#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; }
источник