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枚举处理)
相关推荐
好大哥呀几秒前
C++ IDE
开发语言·c++·ide
BHXDML13 分钟前
JVM 深度理解 —— 程序的底层运行逻辑
java·开发语言·jvm
Wang's Blog16 分钟前
Nodejs-HardCore: 深入解析DBF文件之二进制文件处理指南
开发语言·nodejs
hoiii18717 分钟前
基于LSB匹配的隐写术MATLAB实现程序
开发语言·matlab
J2虾虾23 分钟前
Java使用的可以使用的脚本执行引擎
java·开发语言·脚本执行
幻云201027 分钟前
Next.js指南:从入门到精通
开发语言·javascript·人工智能·python·架构
老马识途2.029 分钟前
java处理接口返回的json数据步骤 包括重试处理,异常抛出,日志打印,注意事项
java·开发语言
CCPC不拿奖不改名34 分钟前
网络与API:从HTTP协议视角理解网络分层原理+面试习题
开发语言·网络·python·网络协议·学习·http·面试
代码游侠44 分钟前
学习笔记——HC-SR04 超声波测距传感器
开发语言·笔记·嵌入式硬件·学习