環境:
- window 10企業版
- .netcore 3.1
- vs 2019 16.4.5
- 控制檯程序以管理員身份運行
參照:
一、window註冊表簡介
註冊表知識點:
- 註冊表有5大根節點,所有的配置都在這5個下面,所以我們讀寫的path裏都以5大根節點字符串開頭(HKEY_LOCAL_MACHINE\SOFTWARE\FileZilla 3)
- 註冊表中有項和值,項就像是文件件、而值就像是一個Dictinary<string,byte[]/int32/int64/string/string[]>
- 註冊表中值的類型
- 字符串
簡單字符串: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
- 字符串
- 註冊表項的默認值
每個項都允許有一個默認值,它的以空字符串("")作爲關鍵字的簡單字符串(注意,不是擴展字符串),如果你設置了它就存在(可以遍歷所有的數據,會發現""),沒設置值得話它就不存在(遍歷數據的時候不會看到"")
二、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
}