How to read a value from the Windows registry How to read a value from the Windows registry windows windows

How to read a value from the Windows registry


Here is some pseudo-code to retrieve the following:

  1. If a registry key exists
  2. What the default value is for that registry key
  3. What a string value is
  4. 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.