前言:.NET 登錄表操作的兩大核心類別
Microsoft.Win32.Registry 提供七大根鍵靜態屬性;RegistryKey 封裝鍵值的開啟、建立、讀寫、刪除、權限控制。兩者皆為 sealed 密封類別。本文系統整理所有公用方法簽章、參數細節、回傳值語意、異常情況、資料型別對應、32/64 位元視圖、遠端操作、存取控制清單 (ACL) 進階用法。
一、Registry 靜態根鍵屬性
public static RegistryKey ClassesRoot { get; } // HKEY_CLASSES_ROOT
public static RegistryKey CurrentUser { get; } // HKEY_CURRENT_USER
public static RegistryKey LocalMachine { get; } // HKEY_LOCAL_MACHINE
public static RegistryKey Users { get; } // HKEY_USERS
public static RegistryKey CurrentConfig { get; } // HKEY_CURRENT_CONFIG
public static RegistryKey DynData { get; } // HKEY_DYN_DATA (已棄用)
public static RegistryKey PerformanceData { get; } // HKEY_PERFORMANCE_DATA (唯讀)
- 屬性回傳
RegistryKey 實例,代表對應根鍵的開啟控制代碼。
- 根鍵實例**不需**也**不可**呼叫
Close()/Dispose()(由框架管理)。
二、RegistryKey 核心方法完整簽章
2.1 開啟/建立子鍵
| 方法 | 簽章 | 語意 |
OpenSubKey | OpenSubKey(string name) | 唯讀開啟子鍵,不存在回傳 null |
| OpenSubKey(string name, bool writable) | writable=true 可寫入,需權限 |
| OpenSubKey(string name, RegistryRights rights) | .NET 4.6+ 精確指定存取權限 |
CreateSubKey | CreateSubKey(string subkey) | 建立或開啟(可寫),回傳新/既有 RegistryKey |
| CreateSubKey(string, bool) | writable 參數(舊版相容) |
| CreateSubKey(string, RegistryKeyPermissionCheck) | .NET 4.6+ Default/ReadWriteSubTree |
| CreateSubKey(string, RegistryKeyPermissionCheck, RegistrySecurity) | 指定 ACL 安全性描述元 |
2.2 遠端基底鍵
public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey, string machineName)
public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey, string machineName, RegistryView view)
RegistryHive 列舉:ClassesRoot、CurrentUser、LocalMachine、Users、CurrentConfig、PerformanceData。
- 遠端機器需啟用「遠端登錄」服務、防火牆開放 RPC (TCP 135/445)、呼叫者具備遠端存取權限。
CurrentUser 無遠端對應(屬於互動會話)。
2.3 刪除子鍵
| 方法 | 簽章 | 語意 |
DeleteSubKey | DeleteSubKey(string subkey) | 刪除指定子鍵,**必須為空**,否則拋 InvalidOperationException |
| DeleteSubKey(string, bool) | throwOnMissingSubKey=false 不存在不拋例外 |
DeleteSubKeyTree | DeleteSubKeyTree(string subkey) | 遞歸刪除子鍵及**所有後代**,不需為空 |
| DeleteSubKeyTree(string, bool) | throwOnMissingSubKey 控制不存在行為 |
2.4 讀取值
| 方法 | 簽章 | 語意 |
GetValue | GetValue(string name) | 回傳 object,不存在回傳 null |
| GetValue(string name, object defaultValue) | 不存在回傳 defaultValue |
GetValueKind | GetValueKind(string name) | 回傳 RegistryValueKind 列舉,不存在拋 IOException |
GetValueNames | GetValueNames() | 回傳所有值名稱陣列 string[] |
GetSubKeyNames | GetSubKeyNames() | 回傳所有子鍵名稱陣列 string[] |
2.5 寫入值
| 方法 | 簽章 | 語意 |
SetValue | SetValue(string name, object value) | 自動推斷型別(字串→String、整數→DWord、長整數→QWord、位元組陣列→Binary、字串陣列→MultiString) |
| SetValue(string name, object value, RegistryValueKind valueKind) | 強制指定型別,避免推斷錯誤 |
2.6 刪除值
public void DeleteValue(string name)
public void DeleteValue(string name, bool throwOnMissingValue)
2.7 關閉與釋放
public void Close() // 釋放非受控 HKEY
public void Dispose() // 介面 IDisposable 實作,同 Close
public void Flush() // 強制將快取寫入磁碟(通常不需手動呼叫)
- 建議使用
using 區塊 確保釋放:using (var key = Registry.CurrentUser.OpenSubKey(...)) { }
2.8 存取控制(.NET 4.6+)
public RegistrySecurity GetAccessControl()
public RegistrySecurity GetAccessControl(AccessControlSections includeSections)
public void SetAccessControl(RegistrySecurity registrySecurity)
// 範例:授予「Users」群組讀寫權限
var security = new RegistrySecurity();
security.AddAccessRule(new RegistryAccessRule(
"Users", RegistryRights.ReadKey | RegistryRights.WriteKey, AccessControlType.Allow));
using (var key = Registry.CurrentUser.CreateSubKey(@"Software\MyApp",
RegistryKeyPermissionCheck.ReadWriteSubTree, security)) { ... }
三、RegistryValueKind 資料型別完整對應
| 列舉值 | Win32 常數 | .NET 型別 | 描述 |
String | REG_SZ | string | 以 null 結尾的 Unicode 字串 |
ExpandString | REG_EXPAND_SZ | string | 含環境變數參考(如 %PATH%) |
DWord | REG_DWORD | int/uint | 32-bit 整數 (Little Endian) |
QWord | REG_QWORD | long/ulong | 64-bit 整數 |
Binary | REG_BINARY | byte[] | 原始位元組陣列 |
MultiString | REG_MULTI_SZ | string[] | 多字串(雙 null 結尾) |
None | REG_NONE | null | 無型別/未定義 |
Unknown | - | - | 無法辨識的型別 |
四、常見異常與處理策略
| 異常型別 | 觸發條件 | 處理策略 |
UnauthorizedAccessException | 權限不足(寫入 HKLM、遠端存取、ACL 拒絕) | 檢查 UAC 提升、管理員身分、遠端服務/防火牆、ACL 設定 |
SecurityException | 程式碼存取安全性 (CAS) 拒絕(.NET Framework 部分信任) | 提升信任層級、簽署強式名稱、調整安全性原則 |
IOException | 登錄表損壞、磁碟滿、GetValueKind 鍵不存在 | 重試、備份還原、檢查磁碟空間 |
ArgumentException | 參數無效(名稱含非法字元、長度超限 255/16383) | 驗證輸入參數 |
InvalidOperationException | DeleteSubKey 非空鍵、關閉後操作 | 改用 DeleteSubKeyTree、檢查物件狀態 |
ObjectDisposedException | 操作已 Dispose 的 RegistryKey | 確保 using 區塊正確、不在 Dispose 後使用 |
五、32/64 位元視圖重導向(RegistryView)
// 開啟 64 位元視圖的 HKLM\Software
using (var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
.OpenSubKey(@"Software\MyApp")) { ... }
// 開啟 32 位元視圖的 HKLM\Software (WoW6432Node)
using (var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)
.OpenSubKey(@"Software\MyApp")) { ... }
- 64 位元進程預設
RegistryView.Default = Registry64。
- 32 位元進程 (WoW64) 預設
RegistryView.Default = Registry32。
- 安裝程式若為 32 位元,寫入
HKLM\Software 實際進入 Wow6432Node;64 位元讀取時需明確指定 RegistryView.Registry32。
六、最佳實務總結
- 永遠使用
using / try/finally 管理 RegistryKey 生命週期,避免控制代碼洩漏。
- 讀取前檢查
null:OpenSubKey/GetValue 可能回傳 null。
- 寫入數值/二進位/多字串時明確指定
RegistryValueKind,避免自動推斷錯誤(如長整數被存為 String)。
- 跨架構部署(32/64 位元)必須指定
RegistryView,否則讀寫位置不一致。
- 敏感資料使用 DPAPI (
ProtectedData) 加密後再寫入,登錄表非加密存儲。
- 避免高頻讀寫:啟動時快取至記憶體,運行期操作快取,關機/變更時同步回寫。
- 單元測試採用介面抽象:
IRegistry + MockRegistry,避免污染真實登錄表。
- 現代 .NET 應用優先使用
appsettings.json + IConfiguration,登錄表保留給系統整合、安裝資訊、檔案關聯、原則設定。
七、快速參考:常用操作單行程式碼
// 讀取字串值(不存在回傳預設值)
string path = Registry.GetValue(@"HKEY_CURRENT_USER\Software\MyApp", "Path", @"C:\Default") as string;
// 寫入 DWORD 值
Registry.SetValue(@"HKEY_CURRENT_USER\Software\MyApp", "Version", 2, RegistryValueKind.DWord);
// 刪除值
Registry.CurrentUser.OpenSubKey(@"Software\MyApp", true)?.DeleteValue("Obsolete", false);
// 檢查鍵是否存在
bool exists = Registry.CurrentUser.OpenSubKey(@"Software\MyApp") != null;
// 列舉所有子鍵名稱
string[] subKeys = Registry.CurrentUser.OpenSubKey(@"Software\MyApp")?.GetSubKeyNames() ?? Array.Empty();
結語
Registry 與 RegistryKey 提供了完整、型別安全、物件導向的登錄表操作 API。掌握根鍵存取、子鍵 CRUD、資料型別對應、RegistryView 跨架構視圖、遠端操作、ACL 權限控制、異常處理與最佳實務,即能在 Windows 平台上安全、高效、可維護地管理應用程式與系統設定。隨著 .NET 跨平台演進,登錄表操作逐漸成為 Windows 專有功能,新專案應優先採用跨平台設定系統(IConfiguration、appsettings.json、環境變數、雲端設定中心)。