1. 程式人生 > 其它 >批量查詢登錄檔鍵值函式 RegQueryMultipleValues 應用一例

批量查詢登錄檔鍵值函式 RegQueryMultipleValues 應用一例

本文連結:

  程式的配置引數可以儲存在登錄檔中,可以用 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 != pszBuffer) delete[]pszBuffer; 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 是登錄檔中該鍵的路徑字串。