C# 注册表操作类

发布于:2025-05-13 ⋅ 阅读:(15) ⋅ 点赞:(0)

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


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

使用示例:

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. 注册表类型对照:

    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语句
    using (var helper = new RegistryHelper(...))
    {
        // 操作代码
    }
    

注意事项:

  • 修改注册表可能影响系统稳定性,操作前建议备份注册表
  • 生产代码中建议添加更详细的日志记录
  • 对于关键系统位置(如系统服务相关项),建议使用Windows API代替直接注册表操作
  • 32/64位系统注册表重定向问题需要注意(可通过使用RegistryView枚举处理)

网站公告

今日签到

点亮在社区的每一天
去签到