Files
Ramitta-lib/Ramitta/RegistryOperations.cs

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
}
}