首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 登錄表程式設計完整指南:Registry/RegistryKey API、權限模型、遠端操作與最佳實務

     編輯:關於C#

前言:登錄表是 Windows 系統與應用程式的中樞設定存儲

.NET 在 Microsoft.Win32 命名空間提供 Registry(根鍵存取)與 RegistryKey(鍵值操作)兩個密封類別,封裝 Win32 Registry API(RegOpenKeyEx、RegSetValueEx、RegQueryValueEx 等)。本文系統整理根鍵對應、CRUD 操作、資料型別對應、權限與 UAC、遠端登錄、RegistryView(32/64 位元視圖)、異常處理與最佳實務。

一、七大根鍵與 Registry 靜態屬性

Registry 屬性Win32 常數用途備註
Registry.ClassesRootHKEY_CLASSES_ROOT檔案關聯、COM 類別註冊、Shell 擴充HKLM\Software\Classes + HKCU\Software\Classes 合併視圖
Registry.CurrentUserHKEY_CURRENT_USER當前使用者設定(應用程式偏好、環境變數)HKU\ 別名,無需管理員權限
Registry.LocalMachineHKEY_LOCAL_MACHINE機器層級設定(驅動程式、服務、系統原則)寫入需管理員權限(UAC 提升)
Registry.UsersHKEY_USERS所有使用者配置檔需管理員權限枚舉
Registry.CurrentConfigHKEY_CURRENT_CONFIG當前硬體設定檔HKLM\System\CurrentControlSet\Hardware Profiles\Current 別名
Registry.DynDataHKEY_DYN_DATA動態硬體資訊(Win9x/Me,已棄用).NET 保留相容性,現代系統無效
Registry.PerformanceDataHKEY_PERFORMANCE_DATA效能計數器原始資料唯讀、需特殊 API 解析

二、RegistryKey 核心 CRUD 方法

2.1 開啟/建立子鍵


// 唯讀開啟(預設)
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\MyApp");

// 讀寫開啟
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\MyApp", writable: true);

// 建立或開啟(自動建立不存在的路徑)
RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\MyApp");

// 建立指定存取控制(.NET 4.6+)
var security = new RegistrySecurity();
security.AddAccessRule(new RegistryAccessRule("Users", RegistryRights.WriteKey, AccessControlType.Allow));
RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\MyApp", true, RegistryOptions.None, security);

2.2 讀取值


// 回傳 object,需自行轉型
object val = key.GetValue("InstallPath");           // 不存在回傳 null
object val = key.GetValue("Version", "1.0.0");      // 不存在回傳預設值
int version = (int)key.GetValue("Version", 1);      // 自動拆箱(需型別匹配)
string path = key.GetValue("Path") as string;       // 安全轉型

// 取得所有值名稱
string[] names = key.GetValueNames();

// 取得值型別(RegistryValueKind)
RegistryValueKind kind = key.GetValueKind("Version"); // String, DWord, QWord, Binary, MultiString, ExpandString, None

2.3 寫入值


key.SetValue("InstallPath", @"C:\Program Files\MyApp");           // 預設 String
key.SetValue("Version", 2, RegistryValueKind.DWord);              // 明確指定 DWORD (32-bit)
key.SetValue("LargeNumber", 1234567890123L, RegistryValueKind.QWord); // QWORD (64-bit)
key.SetValue("BinaryData", new byte[] { 0x01, 0x02, 0x03 }, RegistryValueKind.Binary);
key.SetValue("MultiString", new string[] { "A", "B", "C" }, RegistryValueKind.MultiString);
key.SetValue("ExpandString", @"%ProgramFiles%\MyApp", RegistryValueKind.ExpandString); // 含環境變數

2.4 刪除值與子鍵


key.DeleteValue("ObsoleteValue");           // 刪除單一值
key.DeleteValue("Missing", false);          // false = 不存在不拋例外

key.DeleteSubKey("OldSubKey");              // 僅刪除空子鍵,非空拋例外
key.DeleteSubKeyTree("SubKeyWithChildren"); // 遞歸刪除子鍵及所有後代

2.5 關閉與釋放


key.Close(); // 或 key.Dispose(),釋放非受控 HKEY 控制代碼
// 建議使用 using 區塊
using (var key = Registry.CurrentUser.CreateSubKey(@"Software\MyApp")) {
    key.SetValue("Test", 123);
} // 自動 Dispose

三、資料型別對應表

.NET 型別RegistryValueKindWin32 型別範例
stringString (REG_SZ)以 null 結尾的 Unicode 字串"C:\Path"
int / uintDWord (REG_DWORD)32-bit 整數1024
long / ulongQWord (REG_QWORD)64-bit 整數10000000000
byte[]Binary (REG_BINARY)原始位元組陣列new byte[]{1,2,3}
string[]MultiString (REG_MULTI_SZ)多字串(雙 null 結尾)new[]{"A","B"}
stringExpandString (REG_EXPAND_SZ)含環境變數參考"%TEMP%\file.log"

四、權限模型、UAC 與 RegistryView

4.1 寫入 HKLM 需管理員權限

  • 應用程式資訊清單(app.manifest)設定 <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />。
  • 或程式碼檢測:new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator)。
  • 非管理員寫入 HKLM → UnauthorizedAccessException。

4.2 32/64 位元登錄表視圖重導向

  • 64 位元進程預設存取 64 位元視圖;32 位元進程(WoW64)預設重導向至 HKLM\Software\WOW6432Node。
  • 跨視圖存取(.NET 4+):RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64) / RegistryView.Registry32。

// 64 位元應用讀取 32 位元視圖
using (var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)
                     .OpenSubKey(@"Software\Wow6432Node\MyApp")) { ... }

// 32 位元應用讀取 64 位元視圖
using (var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
                     .OpenSubKey(@"Software\MyApp")) { ... }

五、遠端登錄表操作


// 需遠端機器開啟「遠端登錄」服務、防火牆允許 RPC (TCP 135/445)、具備權限
using (var remoteKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "SERVER01")) {
    using (var subKey = remoteKey.OpenSubKey(@"Software\MyApp", writable: false)) {
        var version = subKey?.GetValue("Version");
    }
}
  • 僅支援 RegistryHive.LocalMachine、Users、ClassesRoot、CurrentConfig。
  • CurrentUser 無遠端對應(屬於互動登入會話)。

六、實戰範例:應用程式安裝資訊登錄與讀取


public static class AppRegistry
{
    private const string AppPath = @"Software\MyCompany\MyApp";

    public static void RegisterInstall(string installPath, string version)
    {
        using (var key = Registry.CurrentUser.CreateSubKey(AppPath, true)) {
            key.SetValue("InstallPath", installPath);
            key.SetValue("Version", version);
            key.SetValue("InstallDate", DateTime.UtcNow.ToString("o"));
            key.SetValue("Features", new[] { "FeatureA", "FeatureB" }, RegistryValueKind.MultiString);
        }
    }

    public static AppInfo GetInstallInfo()
    {
        using (var key = Registry.CurrentUser.OpenSubKey(AppPath, false)) {
            if (key == null) return null;
            return new AppInfo {
                InstallPath = key.GetValue("InstallPath") as string,
                Version = key.GetValue("Version") as string,
                InstallDate = DateTime.TryParse(key.GetValue("InstallDate") as string, out var dt) ? dt : DateTime.MinValue,
                Features = key.GetValue("Features") as string[] ?? Array.Empty()
            };
        }
    }

    public static void Unregister()
    {
        Registry.CurrentUser.DeleteSubKeyTree(AppPath, false);
    }
}

public class AppInfo
{
    public string InstallPath { get; set; }
    public string Version { get; set; }
    public DateTime InstallDate { get; set; }
    public string[] Features { get; set; }
}

七、常見陷阱與最佳實務

  1. 永遠使用 using / try/finally 關閉 RegistryKey,避免控制代碼洩漏。
  2. 讀取前檢查 null:OpenSubKey 不存在回傳 null,GetValue 不存在回傳 null。
  3. 明確指定 RegistryValueKind 寫入數值/二進位/多字串,避免預設 String 導致讀取型別不符。
  4. 64 位元系統跨架構部署:安裝程式若為 32 位元,寫入 HKLM 會進入 Wow6432Node;64 位元讀取時需指定 RegistryView.Registry32。
  5. 敏感資料加密:登錄表非加密存儲,機密資訊(連線字串、Token)務必使用 ProtectedData (DPAPI) 加密後再寫入。
  6. 避免頻繁讀寫:登錄表非高效能資料庫,啟動時快取至記憶體,運行期讀取快取。
  7. 單元測試模擬:介面 IRegistry + MockRegistry 實作,避免測試污染真實登錄表。

八、現代替代方案:應用程式設定檔

方案優點缺點適用場景
appsettings.json + IConfiguration結構化、型別安全、多環境、熱重載、跨平台需檔案系統存取、部署需管理檔案.NET Core / .NET 5+ 應用程式設定
User Secrets (開發環境)敏感資料不進原始碼、專案隔離僅開發環境開發期連線字串、API Key
Azure App Configuration / Consul集中管理、動態更新、審計、多租戶需基礎設施、網路依賴微服務、雲原生
登錄表系統整合、COM/Shell 擴充、舊版相容、機器層級原則Windows 專用、權限複雜、非結構化、難以版控安裝資訊、檔案關聯、系統原則、舊版相容

結語

Microsoft.Win32.Registry/RegistryKey 提供完整的登錄表程式化存取能力。掌握根鍵對應、CRUD 操作、資料型別對應、32/64 位元視圖重導向、遠端操作、權限與 UAC、安全性最佳實務,即能在 Windows 平台上安全、可靠地管理應用程式設定。現代 .NET 應用優先採用 appsettings.json + IConfiguration,登錄表保留給系統整合、安裝資訊、檔案關聯等 Windows 原生場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved