Вопрос

Учитывая ключ для некоторого значения реестра (например, HKEY_LOCAL_MACHINE \ blah \ blah \ blah \ foo), как я могу:

<Ол>
  • Точно определите, что такой ключ существует.
  • Программно (т.е. с кодом) получить его значение.
  • У меня нет абсолютно никакого намерения что-либо записывать обратно в реестр (на время моей карьеры, если я могу помочь). Таким образом, мы можем пропустить лекцию о том, что каждая молекула в моем теле взрывается со скоростью света, если я неправильно пишу в реестр.

    Предпочитаю ответы в C ++, но в основном нужно просто знать, что такое специальное заклинание Windows API для получения значения.

    Это было полезно?

    Решение

    Вот некоторый псевдокод для получения следующего:

    <Ол>
  • Если раздел реестра существует
  • Значение по умолчанию для этого раздела реестра
  • Что такое строковое значение
  • Что такое значение 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;
    }
    

    Другие советы

    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
    

    Пара RegOpenKey и RegQueryKeyEx сделает свое дело.

    Если вы используете MFC класс CRegKey это еще более простое решение.

    RegQueryValueEx

    Это дает значение, если оно существует, и возвращает код ошибки ERROR_FILE_NOT_FOUND, если ключ не существует.

    (Я не могу сказать, работает ли моя ссылка или нет, но если вы просто заглянули в Google по запросу "RegQueryValueEx", первым хитом стала документация по msdn.)

    Начиная с 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);
        auto rc = RegGetValueW(
            HKEY_LOCAL_MACHINE,
            regSubKey.c_str(),
            regValue.c_str(),
            RRF_RT_REG_SZ,
            nullptr,
            static_cast<void*>(&valueBuf.at(0)),
            &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);
            }
            valueBuf.resize(bufferSize);
            rc = RegGetValueW(
                HKEY_LOCAL_MACHINE,
                regSubKey.c_str(),
                regValue.c_str(),
                RRF_RT_REG_SZ,
                nullptr,
                static_cast<void*>(&valueBuf.at(0)),
                &cbData
            );
        }
        if (rc == ERROR_SUCCESS)
        {
            valueBuf.resize(static_cast<size_t>(cbData / sizeof(wchar_t)));
            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-битных программ.

        #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;
        }
    

    Это консольное приложение перечислит все значения и их данные из раздела реестра для большинства потенциальных значений реестра. Есть некоторые странные, которые не часто используются. Если вам нужно поддержать их все, расширьте этот пример, ссылаясь на этот Тип значения реестра документация.

    Пусть это будет содержимое ключа реестра, которое вы можете импортировать из файла .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
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top