C# 注册表操作类

推荐图书
《C# 开发实战1200例》当年就是靠着这本书入门,非常实用优惠券


csharp 复制代码
using Microsoft.Win32;
using System;
using System.Security;

public class RegistryHelper
{
    // 注册表根键枚举
    public enum RegistryRootKey
    {
        ClassesRoot,
        CurrentUser,
        LocalMachine,
        Users,
        CurrentConfig
    }

    private readonly RegistryKey _rootKey;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="rootKey">要操作的注册表根键</param>
    public RegistryHelper(RegistryRootKey rootKey)
    {
        _rootKey = GetRootKey(rootKey);
    }

    /// <summary>
    /// 将枚举转换为实际的RegistryKey对象
    /// </summary>
    private RegistryKey GetRootKey(RegistryRootKey rootKey)
    {
        return rootKey switch
        {
            RegistryRootKey.ClassesRoot => Registry.ClassesRoot,
            RegistryRootKey.CurrentUser => Registry.CurrentUser,
            RegistryRootKey.LocalMachine => Registry.LocalMachine,
            RegistryRootKey.Users => Registry.Users,
            RegistryRootKey.CurrentConfig => Registry.CurrentConfig,
            _ => throw new ArgumentException("Invalid root key")
        };
    }

    /// <summary>
    /// 读取注册表值
    /// </summary>
    /// <param name="subKeyPath">子键路径</param>
    /// <param name="valueName">值名称</param>
    /// <returns>读取到的值,如果不存在返回null</returns>
    public object ReadValue(string subKeyPath, string valueName)
    {
        try
        {
            using RegistryKey? subKey = _rootKey.OpenSubKey(subKeyPath);
            return subKey?.GetValue(valueName);
        }
        catch (SecurityException ex)
        {
            throw new SecurityException("访问注册表需要管理员权限", ex);
        }
        catch (UnauthorizedAccessException ex)
        {
            throw new UnauthorizedAccessException("无权访问注册表项", ex);
        }
    }

    /// <summary>
    /// 写入注册表值
    /// </summary>
    /// <param name="subKeyPath">子键路径</param>
    /// <param name="valueName">值名称</param>
    /// <param name="value">要写入的值</param>
    /// <param name="valueKind">值的类型</param>
    public void WriteValue(string subKeyPath, string valueName, object value, RegistryValueKind valueKind)
    {
        try
        {
            using RegistryKey subKey = _rootKey.CreateSubKey(subKeyPath, true);
            subKey.SetValue(valueName, value, valueKind);
        }
        catch (SecurityException ex)
        {
            throw new SecurityException("写入注册表需要管理员权限", ex);
        }
        catch (UnauthorizedAccessException ex)
        {
            throw new UnauthorizedAccessException("无权写入注册表项", ex);
        }
    }

    /// <summary>
    /// 删除注册表值
    /// </summary>
    /// <param name="subKeyPath">子键路径</param>
    /// <param name="valueName">要删除的值名称</param>
    public void DeleteValue(string subKeyPath, string valueName)
    {
        try
        {
            using RegistryKey? subKey = _rootKey.OpenSubKey(subKeyPath, true);
            subKey?.DeleteValue(valueName, false);
        }
        catch (ArgumentException ex)
        {
            throw new ArgumentException("指定的值不存在", ex);
        }
        catch (SecurityException ex)
        {
            throw new SecurityException("删除注册表值需要管理员权限", ex);
        }
    }

    /// <summary>
    /// 检查子键是否存在
    /// </summary>
    public bool SubKeyExists(string subKeyPath)
    {
        using RegistryKey? subKey = _rootKey.OpenSubKey(subKeyPath);
        return subKey != null;
    }

    /// <summary>
    /// 创建子键
    /// </summary>
    public void CreateSubKey(string subKeyPath)
    {
        try
        {
            _rootKey.CreateSubKey(subKeyPath)?.Dispose();
        }
        catch (SecurityException ex)
        {
            throw new SecurityException("创建子键需要管理员权限", ex);
        }
    }

    /// <summary>
    /// 删除子键(递归删除所有子项)
    /// </summary>
    public void DeleteSubKey(string subKeyPath)
    {
        try
        {
            _rootKey.DeleteSubKeyTree(subKeyPath);
        }
        catch (SecurityException ex)
        {
            throw new SecurityException("删除子键需要管理员权限", ex);
        }
    }

    /// <summary>
    /// 释放资源
    /// </summary>
    public void Dispose()
    {
        _rootKey.Dispose();
        GC.SuppressFinalize(this);
    }
}

使用示例:

csharp 复制代码
class Program
{
    static void Main()
    {
        try
        {
            // 初始化操作CurrentUser下的注册表项
            var helper = new RegistryHelper(RegistryHelper.RegistryRootKey.CurrentUser);

            const string testSubKey = @"Software\RegistryHelperTest";
            const string valueName = "TestValue";

            // 创建测试子键
            if (!helper.SubKeyExists(testSubKey))
            {
                helper.CreateSubKey(testSubKey);
            }

            // 写入测试值
            helper.WriteValue(testSubKey, valueName, 12345, RegistryValueKind.DWord);

            // 读取测试值
            var value = helper.ReadValue(testSubKey, valueName);
            Console.WriteLine($"读取到的值: {value}");

            // 删除测试值
            helper.DeleteValue(testSubKey, valueName);

            // 删除测试子键
            helper.DeleteSubKey(testSubKey);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"操作失败: {ex.Message}");
        }
    }
}

重要说明:

  1. 权限要求:

    • 操作HKEY_LOCAL_MACHINE需要管理员权限
    • 在Visual Studio中运行时需要以管理员身份启动
    • 打包程序时需要设置管理员权限清单
  2. 注册表类型对照:

    csharp 复制代码
    RegistryValueKind.String     // 字符串
    RegistryValueKind.DWord      // 32位整数
    RegistryValueKind.QWord      // 64位整数
    RegistryValueKind.Binary     // 二进制数据
    RegistryValueKind.MultiString // 字符串数组
  3. 异常处理:

    • SecurityException:权限不足
    • UnauthorizedAccessException:访问被拒绝
    • ArgumentException:参数错误
    • 建议在使用时进行try-catch处理
  4. 路径规范:

    • 使用反斜杠分隔路径,例如:@"Software\MyCompany\MyApp"
    • 不要包含根键名称(例如不要写HKEY_CURRENT_USER...)
  5. 资源管理:

    • 类实现了IDisposable接口
    • 长期使用时建议使用using语句
    csharp 复制代码
    using (var helper = new RegistryHelper(...))
    {
        // 操作代码
    }

注意事项:

  • 修改注册表可能影响系统稳定性,操作前建议备份注册表
  • 生产代码中建议添加更详细的日志记录
  • 对于关键系统位置(如系统服务相关项),建议使用Windows API代替直接注册表操作
  • 32/64位系统注册表重定向问题需要注意(可通过使用RegistryView枚举处理)
相关推荐
Wild_Pointer.4 分钟前
项目实战:编写CMakeLists管理Qt+OpenCV项目
开发语言·c++·qt
莫逸风5 分钟前
【java-core-collections】集合框架深度解析
java·开发语言
geovindu7 分钟前
go: Bridge Pattern
开发语言·设计模式·golang·软件构建·桥接模式
Fate_I_C9 分钟前
Kotlin 为什么是 Android 开发的首选语言
android·开发语言·kotlin
格鸰爱童话14 分钟前
python录音转文字
开发语言·python
常利兵14 分钟前
Kotlin 助力 Android 启动“大提速”
android·开发语言·kotlin
黎梨梨梨_15 分钟前
C++入门基础(上)(namespace和缺省参数)
开发语言·c++
卢锡荣28 分钟前
单芯双 C 盲插,一线通显电 ——LDR6020P 盲插 Type‑C 显示器方案深度解析
c语言·开发语言·ios·计算机外设·电脑
legendary_16328 分钟前
PD显示器方案新维度:Type-C充电,投屏,显示技术革新
c语言·开发语言·计算机外设
ic爱吃蓝莓29 分钟前
美团测开一面
java·开发语言