How to read a value from the Windows registry
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
Example code:
Include the library dependency: 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;}
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
Since Windows >=Vista/Server 2008, RegGetValue is available, which is a safer function than RegQueryValueEx. No need for RegOpenKeyEx
, RegCloseKey
or NUL
termination checks of string values (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.