583 lines
20 KiB
C#
583 lines
20 KiB
C#
|
|
using Microsoft.Win32;
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Security;
|
|||
|
|
using System.Text;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
|
|||
|
|
namespace Ramitta.lib
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 注册表操作类 - 提供完整的注册表增删改查功能
|
|||
|
|
/// </summary>
|
|||
|
|
public static class RegistryOperations
|
|||
|
|
{
|
|||
|
|
#region 枚举定义
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 注册表值类型
|
|||
|
|
/// </summary>
|
|||
|
|
public enum RegValueKind
|
|||
|
|
{
|
|||
|
|
String = 1,
|
|||
|
|
ExpandString = 2,
|
|||
|
|
Binary = 3,
|
|||
|
|
DWord = 4,
|
|||
|
|
MultiString = 7,
|
|||
|
|
QWord = 11
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 注册表根键类型
|
|||
|
|
/// </summary>
|
|||
|
|
public enum RegRootKey
|
|||
|
|
{
|
|||
|
|
ClassesRoot,
|
|||
|
|
CurrentUser,
|
|||
|
|
LocalMachine,
|
|||
|
|
Users,
|
|||
|
|
CurrentConfig
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 私有方法
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 解析完整注册表路径
|
|||
|
|
/// </summary>
|
|||
|
|
private static (RegRootKey rootKey, string relativePath) ParseFullPath(string fullPath)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrWhiteSpace(fullPath))
|
|||
|
|
throw new ArgumentException("注册表路径不能为空");
|
|||
|
|
|
|||
|
|
string[] parts = fullPath.Split('\\');
|
|||
|
|
if (parts.Length < 1)
|
|||
|
|
throw new ArgumentException("无效的注册表路径格式");
|
|||
|
|
|
|||
|
|
string rootStr = parts[0].ToUpper();
|
|||
|
|
string relativePath = parts.Length > 1 ? string.Join("\\", parts.Skip(1)) : "";
|
|||
|
|
|
|||
|
|
return rootStr switch
|
|||
|
|
{
|
|||
|
|
"HKEY_CLASSES_ROOT" or "HKCR" => (RegRootKey.ClassesRoot, relativePath),
|
|||
|
|
"HKEY_CURRENT_USER" or "HKCU" => (RegRootKey.CurrentUser, relativePath),
|
|||
|
|
"HKEY_LOCAL_MACHINE" or "HKLM" => (RegRootKey.LocalMachine, relativePath),
|
|||
|
|
"HKEY_USERS" or "HKU" => (RegRootKey.Users, relativePath),
|
|||
|
|
"HKEY_CURRENT_CONFIG" or "HKCC" => (RegRootKey.CurrentConfig, relativePath),
|
|||
|
|
_ => throw new ArgumentException($"不支持的注册表根键: {parts[0]}")
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取RegistryKey根键
|
|||
|
|
/// </summary>
|
|||
|
|
private static RegistryKey GetRootRegistryKey(RegRootKey rootKey)
|
|||
|
|
{
|
|||
|
|
return rootKey switch
|
|||
|
|
{
|
|||
|
|
RegRootKey.ClassesRoot => Registry.ClassesRoot,
|
|||
|
|
RegRootKey.CurrentUser => Registry.CurrentUser,
|
|||
|
|
RegRootKey.LocalMachine => Registry.LocalMachine,
|
|||
|
|
RegRootKey.Users => Registry.Users,
|
|||
|
|
RegRootKey.CurrentConfig => Registry.CurrentConfig,
|
|||
|
|
_ => throw new ArgumentException($"不支持的根键类型: {rootKey}")
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 转换值类型
|
|||
|
|
/// </summary>
|
|||
|
|
private static RegistryValueKind ToRegistryValueKind(RegValueKind valueKind)
|
|||
|
|
{
|
|||
|
|
return valueKind switch
|
|||
|
|
{
|
|||
|
|
RegValueKind.String => RegistryValueKind.String,
|
|||
|
|
RegValueKind.ExpandString => RegistryValueKind.ExpandString,
|
|||
|
|
RegValueKind.Binary => RegistryValueKind.Binary,
|
|||
|
|
RegValueKind.DWord => RegistryValueKind.DWord,
|
|||
|
|
RegValueKind.MultiString => RegistryValueKind.MultiString,
|
|||
|
|
RegValueKind.QWord => RegistryValueKind.QWord,
|
|||
|
|
_ => RegistryValueKind.Unknown
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 查询操作
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 检查注册表项是否存在
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="fullPath">完整注册表路径</param>
|
|||
|
|
/// <returns>是否存在</returns>
|
|||
|
|
public static bool KeyExists(string fullPath)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.OpenSubKey(relativePath);
|
|||
|
|
return key != null;
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 检查注册表值是否存在
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="fullPath">完整注册表路径</param>
|
|||
|
|
/// <param name="valueName">值名称</param>
|
|||
|
|
/// <returns>是否存在</returns>
|
|||
|
|
public static bool ValueExists(string fullPath, string valueName)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.OpenSubKey(relativePath);
|
|||
|
|
return key?.GetValue(valueName) != null;
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取注册表值
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="fullPath">完整注册表路径</param>
|
|||
|
|
/// <param name="valueName">值名称</param>
|
|||
|
|
/// <param name="defaultValue">默认值</param>
|
|||
|
|
/// <returns>读取到的值,如果不存在返回默认值</returns>
|
|||
|
|
public static object ReadValue(string fullPath, string valueName, object defaultValue = null)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.OpenSubKey(relativePath);
|
|||
|
|
|
|||
|
|
return key?.GetValue(valueName, defaultValue) ?? defaultValue;
|
|||
|
|
}
|
|||
|
|
catch (SecurityException ex)
|
|||
|
|
{
|
|||
|
|
throw new UnauthorizedAccessException($"没有权限读取注册表路径: {fullPath}", ex);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"读取注册表值时发生错误: {ex.Message}", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取字符串值
|
|||
|
|
/// </summary>
|
|||
|
|
public static string ReadString(string fullPath, string valueName, string defaultValue = "")
|
|||
|
|
{
|
|||
|
|
return ReadValue(fullPath, valueName, defaultValue) as string ?? defaultValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取整数值(DWORD)
|
|||
|
|
/// </summary>
|
|||
|
|
public static int ReadDWord(string fullPath, string valueName, int defaultValue = 0)
|
|||
|
|
{
|
|||
|
|
object value = ReadValue(fullPath, valueName, defaultValue);
|
|||
|
|
return value is int intValue ? intValue : defaultValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取长整数值(QWORD)
|
|||
|
|
/// </summary>
|
|||
|
|
public static long ReadQWord(string fullPath, string valueName, long defaultValue = 0)
|
|||
|
|
{
|
|||
|
|
object value = ReadValue(fullPath, valueName, defaultValue);
|
|||
|
|
return value is long longValue ? longValue : defaultValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取二进制值
|
|||
|
|
/// </summary>
|
|||
|
|
public static byte[] ReadBinary(string fullPath, string valueName, byte[] defaultValue = null)
|
|||
|
|
{
|
|||
|
|
object value = ReadValue(fullPath, valueName, defaultValue);
|
|||
|
|
return value as byte[] ?? defaultValue ?? Array.Empty<byte>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取多字符串值
|
|||
|
|
/// </summary>
|
|||
|
|
public static string[] ReadMultiString(string fullPath, string valueName, string[] defaultValue = null)
|
|||
|
|
{
|
|||
|
|
object value = ReadValue(fullPath, valueName, defaultValue);
|
|||
|
|
return value as string[] ?? defaultValue ?? Array.Empty<string>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取所有子键名称
|
|||
|
|
/// </summary>
|
|||
|
|
public static string[] GetSubKeyNames(string fullPath)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.OpenSubKey(relativePath);
|
|||
|
|
|
|||
|
|
return key?.GetSubKeyNames() ?? Array.Empty<string>();
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"获取子键列表失败: {ex.Message}", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取所有值名称
|
|||
|
|
/// </summary>
|
|||
|
|
public static string[] GetValueNames(string fullPath)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.OpenSubKey(relativePath);
|
|||
|
|
|
|||
|
|
return key?.GetValueNames() ?? Array.Empty<string>();
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"获取值名称列表失败: {ex.Message}", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取值的数据类型
|
|||
|
|
/// </summary>
|
|||
|
|
public static RegValueKind? GetValueKind(string fullPath, string valueName)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.OpenSubKey(relativePath);
|
|||
|
|
|
|||
|
|
if (key == null) return null;
|
|||
|
|
|
|||
|
|
RegistryValueKind kind = key.GetValueKind(valueName);
|
|||
|
|
return (RegValueKind)kind;
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 新增操作
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 创建注册表项
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="fullPath">完整注册表路径</param>
|
|||
|
|
/// <returns>是否创建成功</returns>
|
|||
|
|
public static bool CreateKey(string fullPath)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.CreateSubKey(relativePath);
|
|||
|
|
return key != null;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"创建注册表项失败: {ex.Message}", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入注册表值
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="fullPath">完整注册表路径</param>
|
|||
|
|
/// <param name="valueName">值名称</param>
|
|||
|
|
/// <param name="value">值数据</param>
|
|||
|
|
/// <param name="valueKind">值类型</param>
|
|||
|
|
public static void WriteValue(string fullPath, string valueName, object value, RegValueKind valueKind = RegValueKind.String)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.CreateSubKey(relativePath);
|
|||
|
|
|
|||
|
|
if (key == null)
|
|||
|
|
throw new InvalidOperationException($"无法创建或打开注册表项: {fullPath}");
|
|||
|
|
|
|||
|
|
RegistryValueKind registryValueKind = ToRegistryValueKind(valueKind);
|
|||
|
|
key.SetValue(valueName, value, registryValueKind);
|
|||
|
|
}
|
|||
|
|
catch (SecurityException ex)
|
|||
|
|
{
|
|||
|
|
throw new UnauthorizedAccessException($"没有权限写入注册表路径: {fullPath}", ex);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"写入注册表值时发生错误: {ex.Message}", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入字符串值
|
|||
|
|
/// </summary>
|
|||
|
|
public static void WriteString(string fullPath, string valueName, string value)
|
|||
|
|
{
|
|||
|
|
WriteValue(fullPath, valueName, value, RegValueKind.String);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入扩展字符串值
|
|||
|
|
/// </summary>
|
|||
|
|
public static void WriteExpandString(string fullPath, string valueName, string value)
|
|||
|
|
{
|
|||
|
|
WriteValue(fullPath, valueName, value, RegValueKind.ExpandString);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入DWORD值
|
|||
|
|
/// </summary>
|
|||
|
|
public static void WriteDWord(string fullPath, string valueName, int value)
|
|||
|
|
{
|
|||
|
|
WriteValue(fullPath, valueName, value, RegValueKind.DWord);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入QWORD值
|
|||
|
|
/// </summary>
|
|||
|
|
public static void WriteQWord(string fullPath, string valueName, long value)
|
|||
|
|
{
|
|||
|
|
WriteValue(fullPath, valueName, value, RegValueKind.QWord);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入二进制值
|
|||
|
|
/// </summary>
|
|||
|
|
public static void WriteBinary(string fullPath, string valueName, byte[] value)
|
|||
|
|
{
|
|||
|
|
WriteValue(fullPath, valueName, value, RegValueKind.Binary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入多字符串值
|
|||
|
|
/// </summary>
|
|||
|
|
public static void WriteMultiString(string fullPath, string valueName, string[] value)
|
|||
|
|
{
|
|||
|
|
WriteValue(fullPath, valueName, value, RegValueKind.MultiString);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 修改操作
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 重命名注册表值
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="fullPath">完整注册表路径</param>
|
|||
|
|
/// <param name="oldValueName">原值名称</param>
|
|||
|
|
/// <param name="newValueName">新值名称</param>
|
|||
|
|
public static void RenameValue(string fullPath, string oldValueName, string newValueName)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// 读取原值
|
|||
|
|
object value = ReadValue(fullPath, oldValueName);
|
|||
|
|
RegValueKind? kind = GetValueKind(fullPath, oldValueName);
|
|||
|
|
|
|||
|
|
if (value == null || kind == null)
|
|||
|
|
throw new InvalidOperationException($"原值不存在或无法读取: {oldValueName}");
|
|||
|
|
|
|||
|
|
// 写入新值
|
|||
|
|
WriteValue(fullPath, newValueName, value, kind.Value);
|
|||
|
|
|
|||
|
|
// 删除原值
|
|||
|
|
DeleteValue(fullPath, oldValueName);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"重命名注册表值失败: {ex.Message}", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 删除操作
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 删除注册表值
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="fullPath">完整注册表路径</param>
|
|||
|
|
/// <param name="valueName">值名称</param>
|
|||
|
|
/// <returns>是否删除成功</returns>
|
|||
|
|
public static bool DeleteValue(string fullPath, string valueName)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.OpenSubKey(relativePath, true);
|
|||
|
|
|
|||
|
|
if (key == null) return false;
|
|||
|
|
|
|||
|
|
key.DeleteValue(valueName, false);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"删除注册表值失败: {ex.Message}", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 删除注册表项
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="fullPath">完整注册表路径</param>
|
|||
|
|
/// <param name="recursive">是否递归删除所有子项</param>
|
|||
|
|
/// <returns>是否删除成功</returns>
|
|||
|
|
public static bool DeleteKey(string fullPath, bool recursive = true)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
|
|||
|
|
if (recursive)
|
|||
|
|
{
|
|||
|
|
root.DeleteSubKeyTree(relativePath, false);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
root.DeleteSubKey(relativePath, false);
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"删除注册表项失败: {ex.Message}", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 高级功能
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 递归获取所有子键
|
|||
|
|
/// </summary>
|
|||
|
|
public static List<string> GetAllSubKeys(string fullPath, int maxDepth = 10)
|
|||
|
|
{
|
|||
|
|
List<string> results = new List<string>();
|
|||
|
|
GetAllSubKeysRecursive(fullPath, results, 0, maxDepth);
|
|||
|
|
return results;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static void GetAllSubKeysRecursive(string currentPath, List<string> results, int currentDepth, int maxDepth)
|
|||
|
|
{
|
|||
|
|
if (currentDepth >= maxDepth) return;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string[] subKeys = GetSubKeyNames(currentPath);
|
|||
|
|
foreach (string subKey in subKeys)
|
|||
|
|
{
|
|||
|
|
string subKeyPath = $"{currentPath}\\{subKey}";
|
|||
|
|
results.Add(subKeyPath);
|
|||
|
|
GetAllSubKeysRecursive(subKeyPath, results, currentDepth + 1, maxDepth);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
// 忽略无权限访问的键
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 备份注册表项到文件
|
|||
|
|
/// </summary>
|
|||
|
|
public static async Task BackupToFile(string fullPath, string outputFilePath)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var (rootKey, relativePath) = ParseFullPath(fullPath);
|
|||
|
|
using RegistryKey root = GetRootRegistryKey(rootKey);
|
|||
|
|
using RegistryKey key = root.OpenSubKey(relativePath);
|
|||
|
|
|
|||
|
|
if (key == null)
|
|||
|
|
throw new InvalidOperationException($"注册表项不存在: {fullPath}");
|
|||
|
|
|
|||
|
|
StringBuilder sb = new StringBuilder();
|
|||
|
|
sb.AppendLine($"注册表备份: {fullPath}");
|
|||
|
|
sb.AppendLine($"备份时间: {DateTime.Now}");
|
|||
|
|
sb.AppendLine("=" + new string('=', 50));
|
|||
|
|
|
|||
|
|
// 备份值
|
|||
|
|
string[] valueNames = key.GetValueNames();
|
|||
|
|
foreach (string valueName in valueNames)
|
|||
|
|
{
|
|||
|
|
object value = key.GetValue(valueName);
|
|||
|
|
RegistryValueKind kind = key.GetValueKind(valueName);
|
|||
|
|
sb.AppendLine($"值: {valueName ?? "(默认)"}");
|
|||
|
|
sb.AppendLine($"类型: {kind}");
|
|||
|
|
sb.AppendLine($"数据: {ConvertValueToString(value, kind)}");
|
|||
|
|
sb.AppendLine();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 备份子键结构
|
|||
|
|
sb.AppendLine("子键结构:");
|
|||
|
|
BackupSubKeysRecursive(key, sb, 1);
|
|||
|
|
|
|||
|
|
await File.WriteAllTextAsync(outputFilePath, sb.ToString(), Encoding.UTF8);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw new InvalidOperationException($"备份注册表失败: {ex.Message}", ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static void BackupSubKeysRecursive(RegistryKey parentKey, StringBuilder sb, int depth)
|
|||
|
|
{
|
|||
|
|
string[] subKeyNames = parentKey.GetSubKeyNames();
|
|||
|
|
foreach (string subKeyName in subKeyNames)
|
|||
|
|
{
|
|||
|
|
sb.AppendLine($"{new string(' ', depth * 2)}[{subKeyName}]");
|
|||
|
|
using RegistryKey subKey = parentKey.OpenSubKey(subKeyName);
|
|||
|
|
if (subKey != null)
|
|||
|
|
{
|
|||
|
|
BackupSubKeysRecursive(subKey, sb, depth + 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static string ConvertValueToString(object value, RegistryValueKind kind)
|
|||
|
|
{
|
|||
|
|
return kind switch
|
|||
|
|
{
|
|||
|
|
RegistryValueKind.String or RegistryValueKind.ExpandString => value as string ?? string.Empty,
|
|||
|
|
RegistryValueKind.DWord => ((int)value).ToString(),
|
|||
|
|
RegistryValueKind.QWord => ((long)value).ToString(),
|
|||
|
|
RegistryValueKind.Binary => BitConverter.ToString((byte[])value),
|
|||
|
|
RegistryValueKind.MultiString => string.Join("; ", (string[])value),
|
|||
|
|
_ => value?.ToString() ?? string.Empty
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|
|||
|
|
}
|