window注册表操作手册

环境:

  • window 10企业版
  • .netcore 3.1
  • vs 2019 16.4.5
  • 控制台程序以管理员身份运行

参照:

一、window注册表简介

1.1 什么是注册表

注册表是window操作系统存储数据的地方,可以认为是window自身的一个小型数据库。所有window软件都可以在安装或运行的时候向注册表添加或读取数据。同时window操作系统也会读取里面的内容以决定自己的行为。
举个例子:

  1. 迅雷软件安装后会在注册表中写入HKEY_CLASSES_ROOT\thunder,从而指示操作系统:当打开thunder://12345这样的地址的时候启动迅雷程序,如下图所示:
    在这里插入图片描述
    在这里插入图片描述
  2. 你可以修改注册表的值,以达到清除快捷方式箭头的目的
    删除HKEY_CLASSES_ROOT\lnkfile项下面的IsShortcut值,然后重启操作系统或者在任务管理器中重启window 资源管理器你就会发现桌面上的图标箭头消失了,如下:
    在这里插入图片描述
  3. 修改注册表项HKEY_CURRENT_USER\Control Panel\Desktop下PaintDesktopVersion的值为1,window桌面右下角将会显示window操作系统版本号:
    在这里插入图片描述
    在这里插入图片描述

1.2 注册表的数据结构

注册表是一个树状结构,它有五大根节点,这五大根节点有不同的作用。根节点下可以有很多子节点,每个子节点称之为“项”,而每个子节点又可以有自己的数据值,这些数据值按照数据类型划分为“字符串”、“扩展字符串”、“多行字符串”、“32位无符号整数”、“64位无符号整数”和“二进制数据”。
在这里插入图片描述

1.2.1 注册表的五大根节点

  • HKEY_CLASSES_ROOT:
    该根键包括启动应用程序所需的全部信息,包括扩展名,应用程序与文档之间的关系,驱动程序名,DDE和OLE信息,类ID编号和应用程序与文档的图标等。
  • HKEY_CURRENT_USER:
    该根键包括当前登录用户的配置信息,包括环境变量,个人程序以及桌面设置等
  • HKEY_LOCAL_MACHINE:
    该根键包括本地计算机的系统信息,包括硬件和操作系统信息,安全数据和计算机专用的各类软件设置信息
  • HKEY_USERS:
    该根键包括计算机的所有用户使用的配置数据,这些数据只有在用户登录系统时才能访问。这些信息告诉系统当前用户使用的图标,激活的程序组,开始菜单的内容以及颜色,字体。
  • HKEY_CURRENT_CONFIG:
    该根键包括当前硬件的配置信息,其中的信息是从KEY_LOCAL_MACHINE中映射出来的。

1.2.2 数据值的数据类型

  • 字符串
    简单字符串:REG_SZ
    多行字符串:REG_MULTI_SZ,获取的是字符串数组,不能解析%windir%等变量
    扩展字符串:REG_EXPAND_SZ,简单字符串上增加解析%windir%等变量的功能
  • 数字(正整数)
    int32:REG_DWORD,双子节 0 - 4294967295(2^32-1)
    int64:REG_QWORD,四个字节 0 - (Math.Pow(2,64)-1)
  • 字节数组
    byte[]:REG_BINARY

1.2.3 注册表项的默认值

每个项都允许有一个默认值,它的以空字符串("")作为关键字的简单字符串(注意,不是扩展字符串),如果你设置了它就存在(可以遍历所有的数据,会发现""),没设置值的话它就不存在(遍历数据的时候不会看到"")

二、c#读写注册表

基于上面对注册表的分析,我们需要对注册表进行读写操作,主要应用RegistryKey对象,下面是我封装的注册表操作的帮助类,200多行,包含的判断、读取、写入等操作:

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
/* 注册表知识点:
 * 1. 注册表有5大根节点,所有的配置都在这5个下面,所以我们读写的path里都以5大根节点字符串开头(HKEY_LOCAL_MACHINE\\SOFTWARE\\FileZilla 3)
 * 2. 注册表中有项和值,项就像是文件夹、而值就像是一个Dictinary<string,byte[]/int32/int64/string/string[]>
 * 3. 注册表中值的类型
 *      字符串
 *          简单字符串:REG_SZ
 *          多行字符串:REG_MULTI_SZ,获取的是字符串数组,不能解析%windir%等变量
 *          扩展字符串:REG_EXPAND_SZ,简单字符串上增加解析%windir%等变量的功能
 *      数字(正整数)
 *          int32:REG_DWORD,双子节 0 - 4294967295(2^32-1)
 *          int64:REG_QWORD,四个字节 0 - (Math.Pow(2,64)-1)
 *      字节数组
 *          byte[]:REG_BINARY
 * 4. 注册表项的默认值
 *      每个项都允许有一个默认值,它的以空字符串("")作为关键字的简单字符串(注意,不是扩展字符串),如果你设置了它就存在(可以遍历所有的数据,会发现""),没设置值的话它就不存在(遍历数据的时候不会看到"")
 * 
 */

namespace ConsoleApp24
{

    public class RegistryUtil
    {
        #region 内部使用
        private static Dictionary<string, RegistryHive> roots = new Dictionary<string, RegistryHive>()
        {
            {"HKEY_CLASSES_ROOT",RegistryHive.ClassesRoot},
            {"HKEY_CURRENT_USER",RegistryHive.CurrentUser},
            {"HKEY_LOCAL_MACHINE",RegistryHive.LocalMachine},
            {"HKEY_USERS",RegistryHive.Users},
            {"HKEY_CURRENT_CONFIG",RegistryHive.CurrentConfig}
        };
        private RegistryKey GetRoot(string path)
        {
            if (string.IsNullOrWhiteSpace(path)) return null;
            path = path.Trim('\\', '/');
            foreach (var i in roots)
            {
                if (path.StartsWith(i.Key))
                {
                    return RegistryKey.OpenBaseKey(i.Value,
                                           Environment.Is64BitOperatingSystem
                                               ? RegistryView.Registry64
                                               : RegistryView.Registry32);
                }
            }
            return null;
        }
        private static ValueTuple<string, RegistryKey> PrunePath(string path)
        {
            path = path.Trim('\\', '/').Replace('/', '\\');
            RegistryKey baseKey = null;
            foreach (var i in roots)
            {
                if (path.StartsWith(i.Key))
                {
                    baseKey = RegistryKey.OpenBaseKey(i.Value,
                                           Environment.Is64BitOperatingSystem
                                               ? RegistryView.Registry64
                                               : RegistryView.Registry32);
                    path = path.Substring(i.Key.Length).Trim('\\');
                    break;
                }
            }
            if (baseKey == null)
            {
                baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
                                           Environment.Is64BitOperatingSystem
                                               ? RegistryView.Registry64
                                               : RegistryView.Registry32);
            }
            return new ValueTuple<string, RegistryKey>(path, baseKey);
        }
        #endregion

        #region 判断、列出数据值的关键字、删除项或数据值
        /// <summary>
        /// 判断注册表项或值是否存在
        /// </summary>
        /// <param name="path">项路径</param>
        /// <param name="keyname">值的名称</param>
        /// <returns></returns>
        public static bool Exists(string path, string keyname = null)
        {
            var res = PrunePath(path);
            var root = res.Item2;
            path = res.Item1;
            RegistryKey key = root.OpenSubKey(path);
            if (key == null) return false;
            if (keyname == null) return true;
            return key.GetValueNames().ToList().Contains(keyname);
        }

        /// <summary>
        /// 返回注册项下的所有数据值名称,如果不存在这个项就返回null
        /// </summary>
        /// <param name="path">注册项路径,如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <returns></returns>
        public static List<string> ListDataKeys(string path)
        {
            var res = PrunePath(path);
            var root = res.Item2;
            path = res.Item1;
            RegistryKey key = root.OpenSubKey(path);
            if (key == null) return null;
            return key.GetValueNames().ToList();
        }

        /// <summary>
        /// 删除指定的项(包括子项和数据值)
        /// </summary>
        /// <param name="path">注册项路径,如:HKEY_CURRENT_CONFIG\test\test1</param>
        public static void DeletePath(string path)
        {
            if (Exists(path))
            {

                ValueTuple<string, RegistryKey> res = PrunePath(path);
                path = res.Item1;
                RegistryKey root = res.Item2;
                root.DeleteSubKeyTree(path);
            }
        }

        /// <summary>
        /// 删除指定项下的指定数据值
        /// </summary>
        /// <param name="path">注册项路径,如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param keyname="keyname">注册项下的数据值关键字,如:teststring</param>
        public static void DeleteValue(string path, string keyname)
        {
            if (Exists(path, keyname))
            {

                ValueTuple<string, RegistryKey> res = PrunePath(path);
                path = res.Item1;
                RegistryKey root = res.Item2;
                RegistryKey key = root.OpenSubKey(path, true);
                key.DeleteValue(keyname);
            }
        }
        #endregion

        #region 读取注册表的值
        private static object GetValue(string path, string keyname = "")
        {
            var res = PrunePath(path);
            var root = res.Item2;
            path = res.Item1;
            RegistryKey key = root.OpenSubKey(path);
            if (key == null) return null;
            var obj = key.GetValue(keyname);
            return obj;
        }

        /// <summary>
        /// 读取注册项下的字符串数据(REG_SZ和REG_EXPAND_SZ),如果keyname为空就是读取默认值
        /// </summary>
        /// <param name="path">项路径,如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据值名称,如:string_a</param>
        /// <returns></returns>
        public static string GetString(string path, string keyname = "")
        {
            var obj = GetValue(path, keyname);
            if (obj == null) return null;
            return obj as string;
        }

        /// <summary>
        /// 读取注册项下的字节数据(REG_BINARY)
        /// </summary>
        /// <param name="path">项路径,如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据值名称,如:binary_123456789</param>
        /// <returns></returns>
        public static byte[] GetByteArray(string path, string keyname)
        {
            var obj = GetValue(path, keyname);
            if (obj == null) return null;
            return obj as byte[];
        }

        /// <summary>
        /// 读取注册项下的字节数据(REG_DWORD)
        /// </summary>
        /// <param name="path">项路径,如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据值名称,如:dword</param>
        /// <returns></returns>
        public static Int32? GetInt32(string path, string keyname)
        {
            var obj = GetValue(path, keyname);
            if (obj == null) return null;
            return (Int32)obj;
        }

        /// <summary>
        /// 读取注册项下的字节数据(REG_QWORD)
        /// </summary>
        /// <param name="path">项路径,如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据值名称,如:qword</param>
        /// <returns></returns>
        public static Int64? GetInt64(string path, string keyname)
        {
            var obj = GetValue(path, keyname);
            if (obj == null) return null;
            return (Int64)obj;
        }

        /// <summary>
        /// 综合GetInt32和GetInt64方法,可以取出REG_DWORD和REG_QWORD类型的数据
        /// </summary>
        /// <param name="path">项路径,如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据值名称,如:testint</param>
        /// <returns></returns>
        public static int? GetInt(string path, string keyname)
        {
            var obj = GetValue(path, keyname);
            if (obj == null) return null;
            if (obj is Int32) return (int)obj;
            if (obj is Int64) return (int)(long)obj;
            return null;
        }

        /// <summary>
        /// 读取注册项下的字节数据(REG_MULTI_SZ)
        /// </summary>
        /// <param name="path">项路径,如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据值名称,如:string_multi</param>
        /// <returns></returns>
        public static string[] GetStringArray(string path, string keyname)
        {
            var obj = GetValue(path, keyname);
            if (obj == null) return null;
            return obj as string[];
        }
        #endregion

        #region 设置注册项的数据值

        private static void SetValue(string path, string keyname, object value, RegistryValueKind dataKind)
        {
            var res = PrunePath(path);
            var root = res.Item2;
            path = res.Item1;
            RegistryKey key = root.CreateSubKey(path, true);
            key.SetValue(keyname, value, dataKind);
        }
        /// <summary>
        /// 设置注册项的默认值,注意:如果指定的path不存在则会新建
        /// </summary>
        /// <param name="path">注册项路径,比如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="value">字符串,类型为REG_SZ</param>
        public static void SetDefault(string path, string value)
        {
            SetValue(path, "", value, RegistryValueKind.String);
        }

        /// <summary>
        /// 给指定注册项设置键值对(REG_SZ),注意:如果指定的path不存在则会新建
        /// </summary>
        /// <param name="path">注册项路径,比如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据的名称</param>
        /// <param name="value">数据值</param>
        public static void SetString(string path, string keyname, string value = "")
        {
            if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必须指定数据值的关键字,如果想设置【(默认)】,那么调用SetDefault(string path,string value)方法");
            SetValue(path, keyname, value, RegistryValueKind.String);
        }

        /// <summary>
        /// 给指定注册项设置键值对(REG_EXPAND_SZ),注意:如果指定的path不存在则会新建
        /// </summary>
        /// <param name="path">注册项路径,比如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据的名称</param>
        /// <param name="value">数据值,如:xiao%windir%ming</param>
        public static void SetStringExpand(string path, string keyname, string value = "")
        {
            if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必须指定数据值的关键字,如果想设置【(默认)】,那么调用SetDefault(string path,string value)方法");
            SetValue(path, keyname, value, RegistryValueKind.ExpandString);
        }

        /// <summary>
        /// 给指定注册项设置键值对(REG_MULTI_SZ),注意:如果指定的path不存在则会新建
        /// </summary>
        /// <param name="path">注册项路径,比如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据的名称</param>
        /// <param name="value">数据值,如:new string[2] { "xiaoming", "xi" }</param>
        public static void SetStringArray(string path, string keyname, string[] value)
        {
            if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必须指定数据值的关键字,如果想设置【(默认)】,那么调用SetDefault(string path,string value)方法");
            if (value == null) throw new Exception("必须指定一个数组!");
            SetValue(path, keyname, value, RegistryValueKind.MultiString);
        }

        /// <summary>
        /// 给指定注册项设置键值对(REG_DWORD),注意:如果指定的path不存在则会新建
        /// </summary>
        /// <param name="path">注册项路径,比如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据的名称</param>
        /// <param name="value">数据值,如:456</param>
        public static void SetInt32(string path, string keyname, Int32 value)
        {
            if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必须指定数据值的关键字,如果想设置【(默认)】,那么调用SetDefault(string path,string value)方法");
            SetValue(path, keyname, value, RegistryValueKind.DWord);
        }

        /// <summary>
        /// 给指定注册项设置键值对(REG_QWORD),注意:如果指定的path不存在则会新建
        /// </summary>
        /// <param name="path">注册项路径,比如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据的名称</param>
        /// <param name="value">数据值,如:789</param>
        public static void SetInt64(string path, string keyname, Int64 value)
        {
            if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必须指定数据值的关键字,如果想设置【(默认)】,那么调用SetDefault(string path,string value)方法");
            SetValue(path, keyname, value, RegistryValueKind.QWord);
        }

        /// <summary>
        /// 综合SetInt32和SetInt64,存储的是RED_DWORD类型,注意:如果指定的path不存在则会新建
        /// </summary>
        /// <param name="path">注册项路径,比如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据的名称</param>
        /// <param name="value">数据值,如:789</param>
        public static void SetInt(string path, string keyname, int value)
        {
            if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必须指定数据值的关键字,如果想设置【(默认)】,那么调用SetDefault(string path,string value)方法");
            SetValue(path, keyname, value, RegistryValueKind.DWord);
        }

        /// <summary>
        /// 给指定注册项设置键值对(REG_BINARY),注意:如果指定的path不存在则会新建
        /// </summary>
        /// <param name="path">注册项路径,比如:HKEY_CURRENT_CONFIG\test\test1</param>
        /// <param name="keyname">数据的名称</param>
        /// <param name="value">数据值,如:new byte[2] { 0x20, 0x45 }</param>
        public static void SetByteArray(string path, string keyname, byte[] value)
        {
            if (string.IsNullOrWhiteSpace(keyname)) throw new Exception("必须指定数据值的关键字,如果想设置【(默认)】,那么调用SetDefault(string path,string value)方法");
            SetValue(path, keyname, value, RegistryValueKind.Binary);
        }
        #endregion
    }
}
### 回答1: 在WPF中,可以使用UserControl来创建自定义的可重用控件,而操作Window的关键是在UserControl中获取对Window的访问权。 要在UserControl中操作Window,首先要在UserControl的代码文件中定义一个依赖属性,该依赖属性类型应为Window,用于保存对Window的引用。例如,可以定义一个名为"ParentWindow"的依赖属性。 然后,在UserControl的XAML文件中,可以将UserControl的父级控件设置为Window,并将该Window与依赖属性进行绑定。可以使用RelativeSource指定绑定的目标为父级窗口。例如,可以在UserControl的根元素上定义"ParentWindow"属性的绑定,绑定源可以为RelativeSource的FindAncestor指令,并指定AncestorType为Window。 接下来,在UserControl的代码文件中,可以使用"ParentWindow"属性来获取对Window的引用,从而可以对Window进行操作。例如,可以在UserControl的某个事件处理程序中使用"ParentWindow"属性来关闭Window,可以使用"ParentWindow.Close()"方法来关闭Window。 总之,要在WPF的UserControl中操作Window,需要先定义一个依赖属性来保存对Window的引用,然后在XAML文件中将UserControl与Window进行绑定,最后在代码中通过该属性来实现对Window的操作。 ### 回答2: 在WPF中,一个UserControl是一种重用的可视化元素,它可以包含其他控件和逻辑代码。可以通过各种方式操作UserControl来实现对Window的操作。 首先,可以通过在UserControl中使用事件来与Window进行通信。在UserControl中定义一个公开的事件,然后在Window中订阅这个事件。当UserControl中触发该事件时,Window中的事件处理程序将被调用,从而实现对Window的操作。 其次,可以通过依赖属性来实现UserControl与Window之间的数据绑定。在UserControl中定义一个依赖属性,然后在Window中将UserControl的某个属性与Window的属性进行绑定。当UserControl中的属性发生变化时,Window中的属性也会自动更新,从而实现对Window的操作。 另外,可以在UserControl中使用VisualTreeHelper类来查找Window的实例,并对其进行操作。通过递归遍历UserControl的子元素,可以在其中找到Window的实例,并进行相应的操作。 还可以通过在UserControl中使用Command来操作Window。定义一个Command,并在UserControl中的某个控件上绑定这个Command。当该控件被触发时,Command会被执行,然后可以在Command的执行方法中对Window进行操作。 最后,还可以通过在UserControl中使用基于消息的通信来操作Window。使用Messenger或EventAggregator等消息传递机制,UserControl可以发送一个消息,然后Window中的订阅者可以接收到这个消息并对Window进行操作。 综上所述,通过事件、数据绑定、遍历可视化树、命令和消息传递等方式,我们可以在UserControl中操作Window,实现丰富的交互和功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jackletter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值