HKEY_LOCAL_MACHINE (機器配置)、HKEY_CURRENT_USER (當前用戶)、HKEY_CLASSES_ROOT (文件關聯/COM)、HKEY_USERS、HKEY_CURRENT_CONFIG。REG_SZ (字串)、REG_DWORD (32位整數)、REG_BINARY (二進位)、REG_MULTI_SZ (多字串)、REG_EXPAND_SZ (含環境變數字串)。RegOpenKeyEx、RegQueryValueEx、RegSetValueEx、RegCloseKey。| 系統 | 路徑 |
|---|---|
| Windows 9x/Me | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion |
| Windows NT/2000/XP/後續 | HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion |
目標值:RegisteredOwner (用戶名)、RegisteredOrganization (公司名)。
CString m_strOwner、m_strCompany。ID_QUERY)、「修改」(ID_MODIFY)。
void CRegeditDlg::OnQuery()
{
UpdateData(TRUE); // 讀取介面輸入(此處僅為習慣)
HKEY hKey = NULL;
LPCTSTR lpSubKey = _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\"); // 注意雙反斜線
// 1. 開啟鍵 (唯讀)
LONG lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ, &hKey);
if (lRet != ERROR_SUCCESS) {
AfxMessageBox(_T("錯誤:無法開啟註冊表鍵值"));
return;
}
// 2. 查詢用戶名
BYTE bufOwner[256] = {0};
DWORD dwType = REG_SZ, dwSize = sizeof(bufOwner);
lRet = ::RegQueryValueEx(hKey, _T("RegisteredOwner"), NULL, &dwType, bufOwner, &dwSize);
if (lRet != ERROR_SUCCESS) {
::RegCloseKey(hKey);
AfxMessageBox(_T("錯誤:無法讀取用戶名"));
return;
}
m_strOwner = (LPCTSTR)bufOwner;
// 3. 查詢公司名
BYTE bufCompany[256] = {0};
dwSize = sizeof(bufCompany);
lRet = ::RegQueryValueEx(hKey, _T("RegisteredOrganization"), NULL, &dwType, bufCompany, &dwSize);
if (lRet != ERROR_SUCCESS) {
::RegCloseKey(hKey);
AfxMessageBox(_T("錯誤:無法讀取公司名"));
return;
}
m_strCompany = (LPCTSTR)bufCompany;
// 4. 關閉鍵並更新介面
::RegCloseKey(hKey);
UpdateData(FALSE);
}
void CRegeditDlg::OnModify()
{
UpdateData(TRUE); // 取得編輯框新值
HKEY hKey = NULL;
LPCTSTR lpSubKey = _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\");
// 1. 開啟鍵 (寫入權限 KEY_WRITE)
LONG lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_WRITE, &hKey);
if (lRet != ERROR_SUCCESS) {
AfxMessageBox(_T("錯誤:無法開啟註冊表鍵值 (需管理員權限)"));
return;
}
// 2. 寫入用戶名
// CString 直接轉 BYTE* (含結束符 \0)
int nLen = m_strOwner.GetLength() + 1;
lRet = ::RegSetValueEx(hKey, _T("RegisteredOwner"), 0, REG_SZ,
(const BYTE*)(LPCTSTR)m_strOwner, nLen * sizeof(TCHAR));
if (lRet != ERROR_SUCCESS) {
::RegCloseKey(hKey);
AfxMessageBox(_T("錯誤:用戶名寫入失敗"));
return;
}
// 3. 寫入公司名
nLen = m_strCompany.GetLength() + 1;
lRet = ::RegSetValueEx(hKey, _T("RegisteredOrganization"), 0, REG_SZ,
(const BYTE*)(LPCTSTR)m_strCompany, nLen * sizeof(TCHAR));
if (lRet != ERROR_SUCCESS) {
::RegCloseKey(hKey);
AfxMessageBox(_T("錯誤:公司名寫入失敗"));
return;
}
::RegCloseKey(hKey);
AfxMessageBox(_T("註冊表修改完成!"));
UpdateData(FALSE);
}
LPBYTE 的正確姿勢原文自寫 CString_To_LPBYTE 分配記憶體極易洩漏。MFC CString 可直接轉型:
// Unicode 建構下 (預設)
(const BYTE*)(LPCTSTR)strVar // 直接指向內部緩衝區,包含結束符
// 長度計算
(strVar.GetLength() + 1) * sizeof(TCHAR)
無需手動 new/delete,安全高效。
寫入 HKLM 需提升權限。專案屬性 → Linker → Manifest File → UAC Execution Level 設為 requireAdministrator,或在 Manifest 中宣告。
CString strPath;
OSVERSIONINFO osvi = { sizeof(OSVERSIONINFO) };
GetVersionEx(&osvi);
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) // 9x/Me
strPath = _T("Software\\Microsoft\\Windows\\CurrentVersion\\");
else
strPath = _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\");
32 位程式訪問 HKLM\Software 會被重定向至 HKLM\Software\WOW6432Node。若需訪問真 64 位視圖,RegOpenKeyEx 加入 KEY_WOW64_64KEY 標誌。
註冊表操作核心在於:**正確路徑、正確權限、正確數據類型、嚴謹錯誤檢查、及時關閉鍵句柄**。本文範例展示了標準的「查詢-修改」閉環流程,配合 MFC DDX 機制,代碼清晰易維護,可直接移植至實際專案中管理應用程式設定。