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

C# 登錄表操作完整指南:建立、讀取、修改、刪除、判斷存在性

     編輯:C# 入門

前言

Windows 登錄表 是系統與應用程式設定的核心儲存庫。C# 透過 Microsoft.Win32.Registry 與 RegistryKey 類別提供完整的受控封裝。本文系統整理登錄表項 (Key) 與值 (Value) 的 CRUD 操作、存在性檢查、預設值處理與最佳實務。

命名空間與根鍵


using Microsoft.Win32;

// 根鍵對應
Registry.ClassesRoot   // HKEY_CLASSES_ROOT
Registry.CurrentUser   // HKEY_CURRENT_USER
Registry.LocalMachine  // HKEY_LOCAL_MACHINE (需管理員權限寫入)
Registry.Users         // HKEY_USERS
Registry.CurrentConfig // HKEY_CURRENT_CONFIG

基本操作模式


// 開啟/建立子鍵 (可寫)
RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\MyApp");
// 僅讀取
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\MyApp", writable: false);
// 使用完畢必須關閉
key?.Close();
// 或使用 using (Net Core 2.1+ RegistryKey 實作 IDisposable)
using (var key = Registry.CurrentUser.OpenSubKey(@"Software\MyApp", true)) { ... }

一、登錄表項 (Key) 操作

1. 建立/確保存在


// 回傳現有或新建的 RegistryKey,若存在不報錯
RegistryKey software = Registry.CurrentUser.CreateSubKey(@"Software\MyApp\Settings");

2. 開啟現有項 (可指定唯讀/可寫)


// 唯讀
using (var key = Registry.CurrentUser.OpenSubKey(@"Software\MyApp"))
{
    // 讀取值...
}

// 可寫 (第二參數 true)
using (var key = Registry.CurrentUser.OpenSubKey(@"Software\MyApp", true))
{
    // 寫入值...
}
若項不存在,OpenSubKey 回傳 null,不拋例外。

3. 刪除項


// 刪除空項
Registry.CurrentUser.DeleteSubKey(@"Software\MyApp\Settings");

// 刪除項及所有子項/值 (遞迴)
Registry.CurrentUser.DeleteSubKeyTree(@"Software\MyApp\Settings");

// 第二參數 throwOnMissing: true(預設) 找不到拋例外,false 不拋
Registry.CurrentUser.DeleteSubKey(@"Software\MyApp\Settings", false);

4. 判斷項是否存在


public static bool KeyExists(RegistryKey root, string subPath)
{
    using (var key = root.OpenSubKey(subPath))
        return key != null;
}

// 用法
bool exists = KeyExists(Registry.CurrentUser, @"Software\MyApp");

二、登錄表值 (Value) 操作

1. 寫入/修改值 (SetValue)


using (var key = Registry.CurrentUser.OpenSubKey(@"Software\MyApp", true))
{
    // 字串 (預設 REG_SZ)
    key.SetValue("UserName", "Admin");

    // 整數 (REG_DWORD)
    key.SetValue("MaxConnections", 100, RegistryValueKind.DWord);

    // 二進位 (REG_BINARY)
    key.SetValue("BinaryData", new byte[] { 0x01, 0x02, 0x03 }, RegistryValueKind.Binary);

    // 多字串 (REG_MULTI_SZ)
    key.SetValue("ServerList", new string[] { "srv1", "srv2" }, RegistryValueKind.MultiString);

    // 展開字串 (REG_EXPAND_SZ) - 含環境變數
    key.SetValue("LogPath", "%APPDATA%\\MyApp\\Logs", RegistryValueKind.ExpandString);

    // QWORD (64位整數)
    key.SetValue("LargeNumber", 9223372036854775807L, RegistryValueKind.QWord);
}

2. 讀取值 (GetValue)


using (var key = Registry.CurrentUser.OpenSubKey(@"Software\MyApp"))
{
    if (key == null) return;

    // 讀取字串
    string name = key.GetValue("UserName") as string ?? "Guest";

    // 讀取整數 (預設 0)
    int maxConn = (int)(key.GetValue("MaxConnections") ?? 0);

    // 讀取二進位
    byte[] bin = key.GetValue("BinaryData") as byte[];

    // 讀取多字串
    string[] servers = key.GetValue("ServerList") as string[];

    // 讀取預設值 (名稱為 null 或空字串)
    string defaultVal = key.GetValue("") as string ?? "(未設定)";
}

3. 刪除值


using (var key = Registry.CurrentUser.OpenSubKey(@"Software\MyApp", true))
{
    key.DeleteValue("UserName", false); // false: 找不到不拋例外
    // 預設值無法刪除,嘗試會拋 ArgumentException
}

4. 判斷值是否存在


public static bool ValueExists(RegistryKey root, string subPath, string valueName)
{
    using (var key = root.OpenSubKey(subPath))
    {
        if (key == null) return false;
        return key.GetValue(valueName) != null;
    }
}

三、完整工具類別


public static class RegistryHelper
{
    public static bool KeyExists(RegistryHive hive, string path)
    {
        using (var baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default))
        using (var key = baseKey.OpenSubKey(path))
            return key != null;
    }

    public static T GetValue(RegistryHive hive, string path, string name, T defaultValue = default)
    {
        using (var baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default))
        using (var key = baseKey.OpenSubKey(path))
        {
            if (key == null) return defaultValue;
            var val = key.GetValue(name);
            return val is T t ? t : defaultValue;
        }
    }

    public static void SetValue(RegistryHive hive, string path, string name, object value, RegistryValueKind kind = RegistryValueKind.String)
    {
        using (var baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default))
        using (var key = baseKey.CreateSubKey(path))
        {
            key.SetValue(name, value, kind);
        }
    }

    public static void DeleteKey(RegistryHive hive, string path, bool recursive = false)
    {
        using (var baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default))
        {
            if (recursive) baseKey.DeleteSubKeyTree(path, false);
            else baseKey.DeleteSubKey(path, false);
        }
    }

    public static string[] GetSubKeyNames(RegistryHive hive, string path)
    {
        using (var baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default))
        using (var key = baseKey.OpenSubKey(path))
            return key?.GetSubKeyNames() ?? Array.Empty();
    }

    public static string[] GetValueNames(RegistryHive hive, string path)
    {
        using (var baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default))
        using (var key = baseKey.OpenSubKey(path))
            return key?.GetValueNames() ?? Array.Empty();
    }
}

// 使用範例
RegistryHelper.SetValue(RegistryHive.CurrentUser, @"Software\MyApp", "Version", "1.0.0");
string ver = RegistryHelper.GetValue(RegistryHive.CurrentUser, @"Software\MyApp", "Version", "0.0.0");

四、32/64 位元登錄表重導向

64 位元系統上,32 位元程式存取 HKLM\Software 會被重導向至 HKLM\Software\WOW6432Node。


// 強制存取 64 位元視圖
using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
using (var key = baseKey.OpenSubKey(@"Software\MyApp", true))
{
    key.SetValue("Test64", "Value");
}

// 強制存取 32 位元視圖
using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
using (var key = baseKey.OpenSubKey(@"Software\MyApp", true))
{
    key.SetValue("Test32", "Value");
}

五、權限與安全性

  • Registry.LocalMachine 寫入需**管理員權限** (UAC 提升)。
  • 使用 RegistryKey.OpenSubKey(path, RegistryRights.WriteKey) 精確控制權限。
  • 敏感資料 (連線字串、金鑰) **勿明文存登錄表**,改用 DPAPI (ProtectedData) 或憑證存放區。

六、常見錯誤與避坑

錯誤原因解決
SecurityException無權限寫入 HKLM啟動器加入 requireAdministrator 或改寫 HKCU
ArgumentException: 預設值無法刪除呼叫 DeleteValue("")預設值只能修改不能刪除
NullReferenceExceptionOpenSubKey 回傳 null 直接操作檢查 null 或使用 ?. 運算子
資料型別不符GetValue 回傳 object 需轉型使用 as / 模式比對 / 轉換方法

總結

掌握 RegistryKey 的 CreateSubKey/OpenSubKey/DeleteSubKeyTree、SetValue/GetValue/DeleteValue、RegistryValueKind 型別、32/64 位元視圖切換、using 釋放資源,即可涵蓋 99% 登錄表操作需求。建議封裝 RegistryHelper 統一錯誤處理與日誌記錄。

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