在 Windows 程式開發中,登錄表是儲存應用程式設定、使用者偏好及系統配置的核心資料庫。雖然 MFC 提供了 CRegKey 類別封裝常用操作,但直接呼叫 Win32 API(RegOpenKeyEx、RegCreateKeyEx、RegSetValueEx、RegQueryValueEx)能更靈活地控制權限、資料型別與錯誤處理。本文以實戰範例示範如何在 HKEY_LOCAL_MACHINE\SOFTWARE 下建立或開啟自訂鍵值,並完成 DWORD 與字串型別的讀寫。
| 函式 | 用途 | 關鍵參數 |
|---|---|---|
RegOpenKeyEx | 開啟現有鍵 | 根鍵、子鍵路徑、存取權限(如 KEY_ALL_ACCESS)、輸出句柄 |
RegCreateKeyEx | 建立或開啟鍵(不存在則建立) | 類別名稱、選項(REG_OPTION_NON_VOLATILE 表永久)、安全屬性、處置狀態 |
RegSetValueEx | 寫入鍵值 | 值名稱、型別(REG_DWORD/REG_SZ)、資料指標、資料長度 |
RegQueryValueEx | 讀取鍵值 | 輸出型別、資料緩衝區、資料長度指標 |
RegCloseKey | 釋放鍵句柄 | 必須在完成操作後呼叫,避免資源洩漏 |
HKEY hKey = HKEY_LOCAL_MACHINE;
LPCTSTR lpszSubKey = _T("SOFTWARE\\MyProgram"); // 注意路徑分隔符
HKEY hKeyResult = NULL;
LONG ret;
DWORD dwType, dwSize;
// 1. 嘗試開啟鍵
ret = RegOpenKeyEx(hKey, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyResult);
if (ret != ERROR_SUCCESS) {
// 2. 開啟失敗 → 建立鍵
ret = RegCreateKeyEx(hKey, lpszSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ | KEY_WRITE,
NULL, &hKeyResult, NULL);
if (ret != ERROR_SUCCESS) {
MessageBox(_T("建立鍵失敗!"));
return;
}
// 3. 寫入預設值:Number (DWORD) 與 Date (字串)
LPCTSTR lpszValueName = _T("Number");
DWORD dwNumber = 10;
RegSetValueEx(hKeyResult, lpszValueName, 0, REG_DWORD,
(CONST BYTE*)&dwNumber, sizeof(DWORD));
lpszValueName = _T("Date");
LPCTSTR lpszDate = _T("2006/4/29");
RegSetValueEx(hKeyResult, lpszValueName, 0, REG_SZ,
(CONST BYTE*)lpszDate, (lstrlen(lpszDate)+1)*sizeof(TCHAR));
RegCloseKey(hKeyResult);
}
else {
// 4. 開啟成功 → 讀取值
DWORD dwRes = 0;
dwType = REG_DWORD;
dwSize = sizeof(DWORD);
ret = RegQueryValueEx(hKeyResult, _T("Number"), 0, &dwType,
(BYTE*)&dwRes, &dwSize);
if (ret != ERROR_SUCCESS) {
MessageBox(_T("讀取 Number 失敗!"));
}
// dwRes 即為讀回的數值
// 讀取字串值
TCHAR szDate[MAX_PATH] = {0};
dwType = REG_SZ;
dwSize = sizeof(szDate);
ret = RegQueryValueEx(hKeyResult, _T("Date"), 0, &dwType,
(BYTE*)szDate, &dwSize);
if (ret != ERROR_SUCCESS) {
MessageBox(_T("讀取 Date 失敗!"));
}
// szDate 即為讀回的字串
RegCloseKey(hKeyResult);
}
\\ 或單一 \(在字串常值中寫成 \\\\),否則會被視為跳脫字元。KEY_READ,需寫入才加 KEY_WRITE,避免因權限不足導致存取被拒。RegSetValueEx 寫 REG_SZ 時,長度應包含結束的 null 字元,建議用 (lstrlen(str)+1)*sizeof(TCHAR)。RegQueryValueEx 取得所需緩衝區大小(傳 NULL 給資料指標),再配置記憶體,防止截斷。LONG,成功為 ERROR_SUCCESS(0),失敗可用 FormatMessage 取得可讀訊息。實務上常將上述邏輯封裝為 CRegistry 工具類別,提供 WriteDWORD、ReadString、DeleteKey、EnumSubKeys 等方法,並搭配 RAII 自動管理 HKEY 生命週期,進一步簡化呼叫端程式碼。