window註冊表操作手冊

環境:

  • window 10企業版
  • .netcore 3.1
  • vs 2019 16.4.5
  • 控制檯程序以管理員身份運行

參照:

一、window註冊表簡介

註冊表知識點:

  1. 註冊表有5大根節點,所有的配置都在這5個下面,所以我們讀寫的path裏都以5大根節點字符串開頭(HKEY_LOCAL_MACHINE\SOFTWARE\FileZilla 3)
  2. 註冊表中有項和值,項就像是文件件、而值就像是一個Dictinary<string,byte[]/int32/int64/string/string[]>
  3. 註冊表中值的類型
    • 字符串
      簡單字符串:REG_SZ
      多行字符串:REG_MULTI_SZ,獲取的是字符串數組,不能解析%windir%等變量
      擴展字符串:REG_EXPAND_SZ,簡單字符串上增加解析%windir%等變量的功能
    • 數字(正整數)
      int32:REG_DWORD,雙子節 0 - 4294967295(2^32-1)
      int64:REG_QWORD,四個字節 0 - (Math.Pow(2,64)-1)
    • 字節數組
      byte[]:REG_BINARY
  4. 註冊表項的默認值
    每個項都允許有一個默認值,它的以空字符串("")作爲關鍵字的簡單字符串(注意,不是擴展字符串),如果你設置了它就存在(可以遍歷所有的數據,會發現""),沒設置值得話它就不存在(遍歷數據的時候不會看到"")

二、c#讀寫註冊表

public class RegistryUtil
{
    #region 內部使用
    private static Dictionary<string, RegistryHive> roots = new Dictionary<string, RegistryHive>()
    {
        {"HKEY_CLASSES_ROOT",RegistryHive.ClassesRoot},
        {"HKEY_CURRENT_USER",RegistryHive.CurrentUser},
        {"HKEY_LOCAL_MACHINE",RegistryHive.LocalMachine},
        {"HKEY_USERS",RegistryHive.Users},
        {"HKEY_CURRENT_CONFIG",RegistryHive.CurrentConfig}
    };
    private RegistryKey GetRoot(string path)
    {
        if (string.IsNullOrWhiteSpace(path)) return null;
        path = path.Trim('\\', '/');
        foreach (var i in roots)
        {
            if (path.StartsWith(i.Key))
            {
                return RegistryKey.OpenBaseKey(i.Value,
                                       Environment.Is64BitOperatingSystem
                                           ? RegistryView.Registry64
                                           : RegistryView.Registry32);
            }
        }
        return null;
    }
    private static ValueTuple<string, RegistryKey> PrunePath(string path)
    {
        path = path.Trim('\\', '/').Replace('/', '\\');
        RegistryKey baseKey = null;
        foreach (var i in roots)
        {
            if (path.StartsWith(i.Key))
            {
                baseKey = RegistryKey.OpenBaseKey(i.Value,
                                       Environment.Is64BitOperatingSystem
                                           ? RegistryView.Registry64
                                           : RegistryView.Registry32);
                path = path.Substring(i.Key.Length).Trim('\\');
                break;
            }
        }
        if (baseKey == null)
        {
            baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
                                       Environment.Is64BitOperatingSystem
                                           ? RegistryView.Registry64
                                           : RegistryView.Registry32);
        }
        return new ValueTuple<string, RegistryKey>(path, baseKey);
    }
    #endregion

    #region 判斷、列出數據值的關鍵字、刪除項或數據值
    /// <summary>
    /// 判斷註冊表項或值是否存在
    /// </summary>
    /// <param name="path">項路徑</param>
    /// <param name="keyname">值得名稱</param>
    /// <returns></returns>
    public static bool Exists(string path, string keyname = null)
    {
        var res = PrunePath(path);
        var root = res.Item2;
        path = res.Item1;
        RegistryKey key = root.OpenSubKey(path);
        if (key == null) return false;
        if (string.IsNullOrWhiteSpace(keyname)) keyname = "";
        return key.GetValueNames().ToList().Contains(keyname);
    }

    /// <summary>
    /// 返回註冊項下的所有數據值名稱,如果不存在這個項就返回null
    /// </summary>
    /// <param name="path">註冊項路徑,如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <returns></returns>
    public static List<string> ListDataKeys(string path)
    {
        var res = PrunePath(path);
        var root = res.Item2;
        path = res.Item1;
        RegistryKey key = root.OpenSubKey(path);
        if (key == null) return null;
        return key.GetValueNames().ToList();
    }

    /// <summary>
    /// 刪除指定的項(包括子項和數據值)
    /// </summary>
    /// <param name="path">註冊項路徑,如:HKEY_CURRENT_CONFIG\test\test1</param>
    public static void DeletePath(string path)
    {
        if (Exists(path))
        {

            ValueTuple<string, RegistryKey> res = PrunePath(path);
            path = res.Item1;
            RegistryKey root = res.Item2;
            root.DeleteSubKeyTree(path);
        }
    }

    /// <summary>
    /// 刪除指定項下的指定數據值
    /// </summary>
    /// <param name="path">註冊項路徑,如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param keyname="keyname">註冊項下的數據值關鍵字,如:teststring</param>
    public static void DeleteValue(string path, string keyname)
    {
        if (Exists(path, keyname))
        {

            ValueTuple<string, RegistryKey> res = PrunePath(path);
            path = res.Item1;
            RegistryKey root = res.Item2;
            RegistryKey key = root.OpenSubKey(path, true);
            key.DeleteValue(keyname);
        }
    }
    #endregion

    #region 讀取註冊表的值
    private static object GetValue(string path, string keyname = "")
    {
        var res = PrunePath(path);
        var root = res.Item2;
        path = res.Item1;
        RegistryKey key = root.OpenSubKey(path);
        if (key == null) return null;
        var obj = key.GetValue(keyname);
        return obj;
    }

    /// <summary>
    /// 讀取註冊項下的字符串數據(REG_SZ和REG_EXPAND_SZ),如果keyname爲空就是讀取默認值
    /// </summary>
    /// <param name="path">項路徑,如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據值名稱,如:string_a</param>
    /// <returns></returns>
    public static string GetString(string path, string keyname = "")
    {
        var obj = GetValue(path, keyname);
        if (obj == null) return null;
        return obj as string;
    }

    /// <summary>
    /// 讀取註冊項下的字節數據(REG_BINARY)
    /// </summary>
    /// <param name="path">項路徑,如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據值名稱,如:binary_123456789</param>
    /// <returns></returns>
    public static byte[] GetByteArray(string path, string keyname)
    {
        var obj = GetValue(path, keyname);
        if (obj == null) return null;
        return obj as byte[];
    }

    /// <summary>
    /// 讀取註冊項下的字節數據(REG_DWORD)
    /// </summary>
    /// <param name="path">項路徑,如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據值名稱,如:dword</param>
    /// <returns></returns>
    public static Int32? GetInt32(string path, string keyname)
    {
        var obj = GetValue(path, keyname);
        if (obj == null) return null;
        return (Int32)obj;
    }

    /// <summary>
    /// 讀取註冊項下的字節數據(REG_QWORD)
    /// </summary>
    /// <param name="path">項路徑,如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據值名稱,如:qword</param>
    /// <returns></returns>
    public static Int64? GetInt64(string path, string keyname)
    {
        var obj = GetValue(path, keyname);
        if (obj == null) return null;
        return (Int64)obj;
    }

    /// <summary>
    /// 綜合GetInt32和GetInt64方法,可以取出REG_DWORD和REG_QWORD類型的數據
    /// </summary>
    /// <param name="path">項路徑,如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據值名稱,如:testint</param>
    /// <returns></returns>
    public static int? GetInt(string path, string keyname)
    {
        var obj = GetValue(path, keyname);
        if (obj == null) return null;
        if (obj is Int32) return (int)obj;
        if (obj is Int64) return (int)(long)obj;
        return null;
    }

    /// <summary>
    /// 讀取註冊項下的字節數據(REG_MULTI_SZ)
    /// </summary>
    /// <param name="path">項路徑,如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據值名稱,如:string_multi</param>
    /// <returns></returns>
    public static string[] GetStringArray(string path, string keyname)
    {
        var obj = GetValue(path, keyname);
        if (obj == null) return null;
        return obj as string[];
    }
    #endregion

    #region 設置註冊項的數據值

    private static void SetValue(string path, string keyname, object value, RegistryValueKind dataKind)
    {
        var res = PrunePath(path);
        var root = res.Item2;
        path = res.Item1;
        RegistryKey key = root.CreateSubKey(path, true);
        key.SetValue(keyname, value, dataKind);
    }
    /// <summary>
    /// 設置註冊項的默認值,注意:如果指定的path不存在則會新建
    /// </summary>
    /// <param name="path">註冊項路徑,比如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="value">字符串,類型爲REG_SZ</param>
    public static void SetDefault(string path, string value)
    {
        SetValue(path, "", value, RegistryValueKind.String);
    }

    /// <summary>
    /// 給指定註冊項設置鍵值對(REG_SZ),注意:如果指定的path不存在則會新建
    /// </summary>
    /// <param name="path">註冊項路徑,比如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據的名稱</param>
    /// <param name="value">數據值</param>
    public static void SetString(string path, string keyname, string value = "")
    {
        if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必須指定數據值的關鍵字,如果想設置【(默認)】,那麼調用SetDefault(string path,string value)方法");
        SetValue(path, keyname, value, RegistryValueKind.String);
    }

    /// <summary>
    /// 給指定註冊項設置鍵值對(REG_EXPAND_SZ),注意:如果指定的path不存在則會新建
    /// </summary>
    /// <param name="path">註冊項路徑,比如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據的名稱</param>
    /// <param name="value">數據值,如:xiao%windir%ming</param>
    public static void SetStringExpand(string path, string keyname, string value = "")
    {
        if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必須指定數據值的關鍵字,如果想設置【(默認)】,那麼調用SetDefault(string path,string value)方法");
        SetValue(path, keyname, value, RegistryValueKind.ExpandString);
    }

    /// <summary>
    /// 給指定註冊項設置鍵值對(REG_MULTI_SZ),注意:如果指定的path不存在則會新建
    /// </summary>
    /// <param name="path">註冊項路徑,比如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據的名稱</param>
    /// <param name="value">數據值,如:new string[2] { "xiaoming", "xi" }</param>
    public static void SetStringArray(string path, string keyname, string[] value)
    {
        if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必須指定數據值的關鍵字,如果想設置【(默認)】,那麼調用SetDefault(string path,string value)方法");
        if (value == null) throw new Exception("必須指定一個數組!");
        SetValue(path, keyname, value, RegistryValueKind.MultiString);
    }

    /// <summary>
    /// 給指定註冊項設置鍵值對(REG_DWORD),注意:如果指定的path不存在則會新建
    /// </summary>
    /// <param name="path">註冊項路徑,比如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據的名稱</param>
    /// <param name="value">數據值,如:456</param>
    public static void SetInt32(string path, string keyname, Int32 value)
    {
        if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必須指定數據值的關鍵字,如果想設置【(默認)】,那麼調用SetDefault(string path,string value)方法");
        SetValue(path, keyname, value, RegistryValueKind.DWord);
    }

    /// <summary>
    /// 給指定註冊項設置鍵值對(REG_QWORD),注意:如果指定的path不存在則會新建
    /// </summary>
    /// <param name="path">註冊項路徑,比如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據的名稱</param>
    /// <param name="value">數據值,如:789</param>
    public static void SetInt64(string path, string keyname, Int64 value)
    {
        if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必須指定數據值的關鍵字,如果想設置【(默認)】,那麼調用SetDefault(string path,string value)方法");
        SetValue(path, keyname, value, RegistryValueKind.QWord);
    }

    /// <summary>
    /// 綜合SetInt32和SetInt64,存儲的是RED_DWORD類型,注意:如果指定的path不存在則會新建
    /// </summary>
    /// <param name="path">註冊項路徑,比如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據的名稱</param>
    /// <param name="value">數據值,如:789</param>
    public static void SetInt(string path, string keyname, int value)
    {
        if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必須指定數據值的關鍵字,如果想設置【(默認)】,那麼調用SetDefault(string path,string value)方法");
        SetValue(path, keyname, value, RegistryValueKind.DWord);
    }

    /// <summary>
    /// 給指定註冊項設置鍵值對(REG_BINARY),注意:如果指定的path不存在則會新建
    /// </summary>
    /// <param name="path">註冊項路徑,比如:HKEY_CURRENT_CONFIG\test\test1</param>
    /// <param name="keyname">數據的名稱</param>
    /// <param name="value">數據值,如:new byte[2] { 0x20, 0x45 }</param>
    public static void SetByteArray(string path, string keyname, byte[] value)
    {
        if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必須指定數據值的關鍵字,如果想設置【(默認)】,那麼調用SetDefault(string path,string value)方法");
        SetValue(path, keyname, value, RegistryValueKind.Binary);
    }
    #endregion
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章