通过修改注册表建立Windows自定义协议

2021-02-19 17:19

阅读:722

YPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">

引言

本文主要介绍注册表的概念与其相关根项的功能,以及浏览器如何通过连接调用自定义协议并与客户端进行数据通信。文中讲及如何通过C#程序、手动修改、安装项目等不同方式对注册表进行修改。其中通过安装项目对注册表进行修改的情况最为常见,在一般的应用程序中都会涉及。
当中最为实用的例子将介绍如何通过"安装项目"修改注册表建立自定义协议,在页面通过ajax方式发送路径请求,并在回调函数中调用自定义协议。
最后一节还将介绍如何调用自定义协议去保持数据的保密性。
希望本篇文章能对各位的学习研究有所帮助,当中有所错漏的地方敬请点评。

 

目录

一、注册表的概念

二、以C#程序修改注册表

三、在 HKEY_CLASSES_ROOT 中添加自定义协议

四、通过“安装项目”方式修改注册表

五、自定义协议的调用

 

 

一、注册表的概念

在谈及Windows自定义协议之前,不得不预先介绍的是注册表这个概念。注册表是windows操作系统的一个核心数据库,其作用是充当计算机上操作系统和应用程序的中央信息储存库,用于存放着各种系统级参数。它能直接控制着windows的启动、硬件驱动程序的装载以及一些windows应用程序的运行。
注册表中保存有应用程序和资源管理器外壳的初始条件、首选项和卸载数据等,联网计算机的整个系统的设置和各种许可,文件扩展名与应用程序的关联,硬件部件的描述、状态和属性,性能记录和其他底层的系统状态信息,以及其他数据等。

1.1 打开注册表

打开 "windows运行",然后输入regedit或regedt32即可打开注册表

技术分享图片

 

1.2 注册表结构

注册表由键、子键和值项构成,一个键就是分支中的一个文件夹,而子键就是这个文件夹中的子文件夹,子键同样是一个键。一个值项则是一个键的当前定义,由名称、数据类型以及分配的值组成。一个键可以有一个或多个值,每个值的名称各不相同,如果一个值的名称为空,则该值为该键的默认值。

HKEY_CLASSES_ROOT 用于控制所有文件的扩展和所有可执行文件相关的信息,本章提到的Windows自定义协议也是在此项中注册产生的(在后面章节将详细讲述);

HEKY_CURRENT_USER  用于管理系统当前的用户信息,及其应用程序的相关资料,例如:当前登录的用户信息,包括用户登录用户名和暂存的密码、当前用户使用的应用软件信息等。用户登录时,其信息会在HEKY_USER表中拷贝到此表中,当HEKY_USER表中信息发生改动时,HEKY_CURRENT_USER表中的信息也将随之改动;

HKEY_CURRENT_MACHINE  用于存储控制系统和软件的信息,当中包括网络和硬件上所有的软件设备信息,比如文件的位置,注册和未注册的状态,版本号等等;比较常用的例如在HKEY_LOCAL_MACHINE\Microsoft\Windows\CurrentVersion\Run下注册程序,程序就会在Windows启动时自动运行等等。其实在HKEY_LOCAL_MACHINE\SOFTWARE\Classes里面就包含了HKEY_CLASSES_ROOT信息,而HKEY_CLASSES_ROOT只是它的一个键值的映射,方便信息管理而已;

HEKY_USER  作用是把缺省用户和目前登陆用户的信息输入到注册表编辑器,但它仅被那些配置文件激活的登陆用户使用。当任何在HKEY_CURRENT_USER里的信息发生改变,HKEY_USERS里面的信息也会相应改动。

HKEY_CURRENT_CONFIG 用于存储当前系统的配置方式,例如当Windows为同一个硬件安装有多种驱动程序时,会在HEKY_CUREENT_MACHINE中记录多个程序信息,而在HEKY_CURRENT_CONFIG中只是存储默认使用的驱动信息,Windows 启动时会默认按照HEKY_CURRENT_CONFIG中的配置调用相关的驱动程序;

 

二、以C#程序修改注册表

微软建立了Registry、RegistryKey 常用类用于修改Windows 注册表中的节点。

2.1 Registry 类

Registry 主要用作获取 Windows 注册表中的根项的 RegistryKey 对象,并提供访问项/值对的 static 方法。
它有以下几个常用的属性可直接用于获取HEKY_CUREENT_MACHINE、HKEY_CLASSES_ROOT等几个基础项

属性 说明
ClassesRoot 定义文档的类型(或类)以及与那些类型关联的属性。 该字段读取 Windows 注册表基项 HKEY_CLASSES_ROOT。
CurrentConfig 包含有关非用户特定的硬件的配置信息。 该字段读取 Windows 注册表基项 HKEY_CURRENT_CONFIG。
CurrentUser 包含有关当前用户首选项的信息。 该字段读取 Windows 注册表基项 HKEY_CURRENT_USER
DynData 已过时包含动态注册表数据。 该字段读取 Windows 注册表基项 HKEY_DYN_DATA。
LocalMachine 包含本地计算机的配置数据。 该字段读取 Windows 注册表基项 HKEY_LOCAL_MACHINE。
PerformanceData 包含软件组件的性能信息。 该字段读取 Windows 注册表基项 HKEY_PERFORMANCE_DATA。
Users 包含有关默认用户配置的信息。 该字段读取 Windows 注册表基项 HKEY_USERS。

Registry属性表2.1.1

 

Registry 也提供几个常用方法用于获取或设置注册表中指定名称的项值。

方法 说明
GetValue (String, String, Object) 检索与指定的注册表项中的指定名称关联的值。  如果在指定的项中未找到该名称,则返回您提供的默认值;或者,如果指定的项不存在,则返回 null。    
SetValue(String, String, Object)   设置指定的注册表项的指定名称/值对。  如果指定的项不存在,则创建该项。    
SetValue(String, String, Object, RegistryValueKind)   通过使用指定的注册表数据类型,设置该指定的注册表项的名称/值对。  如果指定的项不存在,则创建该项。    

Registry方法表2.1.2

 

2.2 RegistryKey 类

RegistryKey类主要用于管理 Windows 注册表中的项级节点,通过 Registry 类的属性就可以获取注册表中的根节点。它包含了以下几个常用属性   

属性 说明
Handle 获取一个 SafeRegistryHandle 对象,该对象表示当前 RegistryKey 对象封装的注册表项。
Name 检索项的名称。
SubKeyCount 检索当前项的子项数目。
ValueCount 检索项中值的计数。
View 获取用于创建注册表项的视图。

RegistryKey属性表2.2.1

 

RegistryKey类的方法比较多,通过CreateSubKey(String)、GetValue(String)、SetValue(String, Object)、DeleteValue(String)等常用方法,就可以实现对注册表的查询修改。下面简单介绍一下RegistryKey的几个常用方法   

方法 说明
Close() 关闭该项,如果该项的内容已修改,则将该项刷新到磁盘。
CreateSubKey(String) 创建一个新子项或打开一个现有子项以进行写访问。
CreateSubKey(String, RegistryKeyPermissionCheck) 使用指定的权限检查选项创建一个新子项或打开一个现有子项以进行写访问。
CreateSubKey(String, RegistryKeyPermissionCheck, RegistryOptions) 使用指定的权限检查和注册表选项,创建或打开一个用于写访问的子项。
CreateSubKey(String, RegistryKeyPermissionCheck, RegistrySecurity) 使用指定的权限检查选项和注册表安全性创建一个新子项或打开一个现有子项以进行写访问。
CreateSubKey(String, RegistryKeyPermissionCheck, RegistryOptions, RegistrySecurity) 使用指定的权限检查选项、注册表选项和注册表安全性,创建或打开一个用于写访问的子项。
DeleteSubKey(String) 删除指定的子项。
DeleteSubKey(String, Boolean) 删除指定的子项,并指定在找不到该子项时是否引发异常。
DeleteSubKeyTree(String) 递归删除子项和任何子级子项。
DeleteSubKeyTree(String, Boolean) 以递归方式删除指定的子项和任何子级子项,并指定在找不到子项时是否引发异常。
DeleteValue(String) 从此项中删除指定值。
DeleteValue(String, Boolean) 从此项中删除指定的值,并指定在找不到该值时是否引发异常。
Flush() 将指定的打开注册表项的全部特性写到注册表中。
GetSubKeyNames() 检索包含所有子项名称的字符串数组。
GetValue(String) 检索与指定名称关联的值。  如果注册表中不存在名称/值对,则返回 null。 
GetValue(String, Object) 检索与指定名称关联的值。  如果未找到名称,则返回您提供的默认值。 
GetValue(String, Object, RegistryValueOptions) 检索与指定的名称和检索选项关联的值。  如果未找到名称,则返回您提供的默认值。 
SetValue(String, Object) 设置指定的名称/值对。

RegistryKey方法表2.2.2

 

2.3 应用实例

下面先通过几个例子,简单介绍一下如何通过 Registry、RegistryKey 类修改系统注册表。

2.3.1 新建自定义的项

下面应用程序将会在注册表中新建 MyApplication项,并在其子项Path的默认值中保存应用程序的StartupPath、在AppPath值中保存应用程序的UserAppDataPath

技术分享图片
        static void Main(string[] args)
        {
            //获取Machine根项
            RegistryKey machine = Registry.LocalMachine;
            //打开SOFTWARE项
            RegistryKey software = machine.OpenSubKey("SOFTWARE", true);
            //新项MyApplication项
            RegistryKey myApplication = software.CreateSubKey("MyApplication");
            RegistryKey subkey = myApplication.CreateSubKey("Path");
            //新建键值,当键值名称为空时,将被设置为默认值
            subkey.SetValue(null, Application.StartupPath);
            subkey.SetValue("AppPath", Application.UserAppDataPath);
        }
技术分享图片

运行应用程序后,打开"windows运行",然后输入regedit,在注册表LocalMachine项中可以查找到新建的MyApplication项

技术分享图片

 

2.3.2 开机启动 “命令提示符”

注册表所包含的信息很多,其中在“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run”处正是用于Windows开机启动的程序信息。下面以Windows自带的“命令提示符”工具为例子,通过修改注册表实现开机启动。(说明:"命令提示符"的路径是在“C:\Windows\System32\cmd.exe”)

技术分享图片
      static void Main(string[] args)
        {
            //打开注册表子项
            RegistryKey key = Registry.LocalMachine
                .OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
            //增加开机启动项
            key.SetValue("Cmd", "C:\\Windows\\System32\\cmd.exe");
        }
技术分享图片

修改后可以看到注册表中在“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run”中会增加了一个名为Cmd的键

技术分享图片

当重启计算机时就会看到“命令提示符”将自动启动

技术分享图片

 

 

三、在 HKEY_CLASSES_ROOT 中添加自定义协议

上面的章节已经简单介绍如何通过程序操作注册表,下面将介绍一下如果通过修改HKEY_CLASSES_ROOT中的项,建立自定义协议。
首先建立一个应用程序MyApplication,写入简单的Hello World测试代码

   static void Main(string[] args)
        {
            Console.WriteLine("Hello World");
            Console.ReadKey();
        }

手动在注册表中建立下面的项和键:

  • 1、在HKEY_CLASSES_ROOT下添加项MyApplication.
  • 2、修改MyApplication项下的默认值输入"URL:(可为空)"。
  • 3、在MyApplication项下再添加一个键值"URL Protocol"。(必要健,否则在IE浏览器中可能无法运行)
  • 4、在MyApplication项下新建项"shell"
  • 5、在shell项下新建项"open"
  • 6、在open项下新建项"command"
  • 7、修改command项的默认键值为MyApplication应用程序的路径 "D:\C# Projects\MyApplication.exe" "%1"

注意:把 command 键值设置为 "D:\C# Projects\MyApplication.exe" "%1",只要当中包含标示符“%1”,应用程序可以根据自定义协议的路径获取对应的参数,其使用方式将在下面的章节再详细说明。

技术分享图片

技术分享图片

简单测试:建立一个HTML页面,如入以下代码。
注意:此连接路径正是以注册表产首项的MyApplication名称相同。

技术分享图片
  ......

 
     Hello World
   
技术分享图片

当按下Hello World连接符时,系统就会调用自定义协议MyApplication,启动“D:\C# Projects\MyApplication.exe”

技术分享图片

 

四、通过“安装项目”方式修改注册表

4.1 建立应用程序

上面章节所介绍的只是自定义协议的简单使用方式,然而在做软件项目的时候,无论是使用C/S或者B/S方式,自定义协议都必须实现在客户端的自动安装才能使用,因此客户端的注册表设置只能通过程序进行修改。有见及此,微软早在“安装项目”中设置了注册表修改功能。下面的章节将为大家介绍如何通过 Visual Studio 2010 的“安装项目”,实现注册表的修改。
建立一个新的MyApplication应用程序,输入以下代码。

技术分享图片
    [DataContract]
    public class Person
    {
        [DataMember]
        public int ID;
        [DataMember]
        public string Name;
        [DataMember]
        public int Age;
    }

    class Program
    {
        static void Main(string[] args)
        {
            if (args != null)
            {
                //获取输入参数
                string data = args[0].Split(‘&‘)[1];
                //把JSON转换成Person对象
                Person person = GetPerson(data);
                //数据显示
                Console.WriteLine(person.Name + "‘s age is:" + person.Age);
                Console.ReadKey();
            }
        }

        //数据转换
        static Person GetPerson(string data)
        {
            DataContractJsonSerializer serializer = new 
                DataContractJsonSerializer(typeof(Person));
            MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(data));
            Person person = (Person)serializer.ReadObject(stream);
            stream.Close();
            return person;
        }
    }
技术分享图片

 

4.2 添加安装项目

然后在解决方案里面添加一个“安装项目”

技术分享图片

右键点击"安装项目",选择“视图-文件系统&a


评论


亲,登录后才可以留言!