批量查询注册表键值函数 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 是注册表中该键的路径字符串。

posted @ 2021-07-30 18:39  jqdy  阅读(386)  评论(0编辑  收藏  举报