批量查询注册表键值函数 RegQueryMultipleValues 应用一例
本文链接:https://www.cnblogs.com/jqdy/p/15080977.html
程序的配置参数可以存储在注册表中,可以用 RegQueryMultipleValues() API 一次性获得注册键下的多个值。
该函数定义在 Winreg.h 中,微软官方说明。
LSTATUS RegQueryMultipleValuesA(
HKEY hKey, // 已注册键的句柄
PVALENTA val_list, // 指向 VALENT 结构数组的指针,该结构数组返回查询的结果
DWORD num_vals, // 结构数组的长度
LPSTR lpValueBuf,// 指向一个缓冲区的指针,查询成功时存储返回的值。另一用法,另该参数=NULL,下个参数ldwTotsize=0,执行该参数后,ldwTotsize会返回结构数组的占用的空间大小(byte)
LPDWORD ldwTotsize // 返回写入上个参数 lpValueBuf 的字节大小
);
返回值:查询成功返回 ERROR_SUCCESS。
下面的例子是一个服务程序加载时,需要查询连接数据库的连接字符串。
因为服务程序会一直驻留内存,所以连接字符串的内存在函数中分配,需要多少分配多少,没有浪费。也可以给函数传入分配好地址的字符串指针,省却在函数内分配内存的工作,虽然安全一些,但是,势必会造成提前分配较大的空间,有一些浪费内存。
#include <windows.h> #include <strsafe.h> #define KEY_VALUE_COUNT 7 // 有7个参数需要查询 // 获取ADO连接字符串 // 参数: // pszStr:连接字符串指针,为一空指针,空间在本函数内分配,无用时调用HeapFree()释放 // 返回:查询是否成功 BOOL GetAdoCnStr(PTSTR& pszStr) { TCHAR pszProvider[] = TEXT("Provider"); TCHAR pszServerIp[] = TEXT("ServerIp"); TCHAR pszServerPort[] = TEXT("ServerPort"); TCHAR pszInstanceName[] = TEXT("InstanceName"); TCHAR pszDatabase[] = TEXT("Database"); TCHAR pszUserId[] = TEXT("UserId"); TCHAR pszPassword[] = TEXT("Password");
DWORD nErrorCode; BOOL flag = TRUE; TCHAR pszBuf[1024] = { 0 }; // 定义RegQueryMultipleValues()相关变量 VALENT pValent[KEY_VALUE_COUNT] = { 0 };// RegQueryMultipleValues查询返回的VALENT数组 DWORD cValent = KEY_VALUE_COUNT; // VALENT(Key-Value)的个数 LPTSTR pValeBuffer = NULL; // 查询返回缓冲区 DWORD cbValueBuffer = 0; // 查询返回缓冲区的字节数 HKEY hKey = NULL; do { if (FALSE == GetRegistryHandle(hKey, nErrorCode))// 获取注册表键值句柄,失败时nErrorCode返回错误代码 { flag = FALSE; break; } pValent[0].ve_valuename = pszProvider; pValent[1].ve_valuename = pszServerIp; pValent[2].ve_valuename = pszServerPort; pValent[3].ve_valuename = pszInstanceName; pValent[4].ve_valuename = pszDatabase; pValent[5].ve_valuename = pszUserId; pValent[6].ve_valuename = pszPassword; // 查询返回缓冲区的大小(cbValueBuffer,初值必须为0),in bytes. RegQueryMultipleValues(hKey, pValent, cValent, NULL, &cbValueBuffer); if (cbValueBuffer == 0) { flag = FALSE; break; } pValeBuffer = new TCHAR[cbValueBuffer / sizeof(TCHAR)]; // 上面查出的cbValueBuffer为bytes,所以要除以2 // 查询VALENT数组所有的键值 if (ERROR_SUCCESS != RegQueryMultipleValues(hKey, pValent, cValent, pValeBuffer, &cbValueBuffer)) { flag = FALSE; break; } // 合成连接字符串 StringCchPrintf(pszBuffer, BUFFER_SIZE, TEXT("Provider=%s;Data Source=%s,%s\\%s;Database=%s;User Id=%s;Password=%s;"), pValent[0].ve_valueptr, pValent[1].ve_valueptr, pValent[2].ve_valueptr, pValent[3].ve_valueptr, pValent[4].ve_valueptr, pValent[5].ve_valueptr, pValent[6].ve_valueptr); // 取得默认堆句柄 HANDLE hDefaultHeap = GetProcessHeap(); if (!hDefaultHeap) { flag = FALSE; break; } // 分配堆内存,应该是malloc的底层实现。在声明 g_pszAdoCnStr 的程序退出时要调用 HeapFree 释放。 size_t nByteLen; StringCbLength(pszBuffer, 1024, &nByteLen); // 计算的长度包不含末尾的NULL nByteLen += sizeof(TCHAR); // 将末尾NULL加进来 pszStr = (PTCHAR)HeapAlloc(hDefaultHeap, 0, nByteLen); // 0:分配失败返回NULL,而是不抛出异常 StringCchCopy(pszStr, nByteLen / sizeof(TCHAR), pszBuffer); if (!pszStr) { flag = FALSE; break; } } while (0); if (NULL != pValeBuffer) delete[]pValeBuffer; if (NULL != hKey) RegCloseKey(hKey); return flag; }
// Function: 获取注册表中相应键(已写死)的句柄 // Parameters: // phKey: 返回的句柄 // nErrorCode: 失败时返回 winerror.h 中的错误代码 // Returns: 成功/失败 BOOL GetRegistryHandle(HKEY& phKey, DWORD& nErrorCode) { nErrorCode = RegCreateKeyEx( HKEY_LOCAL_MACHINE, //根 REGISTRY_SERVICE_PATH, //键名 0, //保留 NULL, //自定义类型,可为NULL REG_OPTION_NON_VOLATILE,//保存 KEY_ALL_ACCESS, //得到的hKey句柄具有所有权限 NULL, //得到的hKey是否可继承 &hKey, //得到的hKey句柄 NULL); //建立的键值是否已经存在,REG_CREATED_NEW_KEY、REG_OPENED_EXISTING_KEY,NULL不需要返回 return (ERROR_SUCCESS == nErrorCode) ? TRUE : FALSE; }
其中:REGISTRY_SERVICE_PATH 是注册表中该键的路径字符串。