批量查詢登錄檔鍵值函式 RegQueryMultipleValues 應用一例
阿新 • • 發佈:2021-07-30
本文連結:
程式的配置引數可以儲存在登錄檔中,可以用 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 是登錄檔中該鍵的路徑字串。