c++ - Cómo leer un valor del registro de Windows
winapi registry (6)
Dada la clave para algún valor de registro (por ejemplo, HKEY_LOCAL_MACHINE / blah / blah / blah / foo) ¿cómo puedo:
- Determine con seguridad que existe esa clave.
- Programáticamente (es decir, con código) obtiene su valor.
No tengo ninguna intención de escribir nada en el registro (durante mi carrera si puedo evitarlo). Así que podemos omitir la conferencia sobre cada molécula de mi cuerpo explotando a la velocidad de la luz si escribo incorrectamente en el registro.
Prefiero las respuestas en C ++, pero sobre todo solo necesito saber cuál es el encantamiento especial de la API de Windows para obtener el valor.
Desde Windows> = Vista / Server 2008, RegGetValue está disponible, que es una función más segura que RegQueryValueEx . No es necesario realizar RegOpenKeyEx
de RegOpenKeyEx
de RegOpenKeyEx
, RegCloseKey
o NUL
de valores de cadena ( 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);
DWORD cbData = (DWORD)bufferSize;
auto rc = RegGetValueW(
HKEY_LOCAL_MACHINE,
regSubKey.c_str(),
regValue.c_str(),
RRF_RT_REG_SZ,
nullptr,
(void*)&valueBuf.at(0),
&cbData
);
while (rc == ERROR_MORE_DATA)
{
// Get a buffer that is big enough.
cbData /= sizeof(wchar_t);
if (cbData > (DWORD)bufferSize)
{
bufferSize = (size_t)cbData;
}
else
{
bufferSize *= 2;
cbData = (DWORD)bufferSize;
}
valueBuf.resize(bufferSize);
rc = RegGetValueW(
HKEY_LOCAL_MACHINE,
regSubKey.c_str(),
regValue.c_str(),
RRF_RT_REG_SZ,
nullptr,
(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;
}
Su parámetro dwFlags
admite flags para la restricción de tipo, llenando el buffer de valores con ceros cuando falla ( RRF_ZEROONFAILURE
) y acceso de registro de 32 / 64bit ( RRF_SUBKEY_WOW6464KEY
, RRF_SUBKEY_WOW6432KEY
) para programas de 64 bits.
El par de RegOpenKey y RegQueryKeyEx hará el truco.
Si utiliza MFC, la clase CRegKey es una solución aún más fácil.
Esto proporciona el valor si existe y devuelve un código de error ERROR_FILE_NOT_FOUND si la clave no existe.
(No puedo decir si mi enlace funciona o no, pero si busca en Google "RegQueryValueEx", el primer acierto es la documentación de msdn).
Aquí hay un pseudocódigo para recuperar lo siguiente:
- Si existe una clave de registro
- Cuál es el valor predeterminado para esa clave de registro
- Qué valor de cadena es
- Qué valor DWORD es
Código de ejemplo:
Incluir la dependencia de la biblioteca: 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;
}
#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;
}
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