引言
本文主要介紹注冊表的概念與其相關根項的功能,以及浏覽器如何通過連接調用自定義協議並與客戶端進行數據通信。文中講及如何通過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等幾個基礎項
Registry屬性表2.1.1
Registry 也提供幾個常用方法用於獲取或設置注冊表中指定名稱的項值。
Registry方法表2.1.2
2.2 RegistryKey 類
RegistryKey類主要用於管理 Windows 注冊表中的項級節點,通過 Registry 類的屬性就可以獲取注冊表中的根節點。它包含了以下幾個常用屬性
RegistryKey屬性表2.2.1
RegistryKey類的方法比較多,通過CreateSubKey(String)、GetValue(String)、SetValue(String, Object)、DeleteValue(String)等常用方法,就可以實現對注冊表的查詢修改。下面簡單介紹一下RegistryKey的幾個常用方法
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(); }
手動在注冊表中建立下面的項和鍵:
注意:把 command 鍵值設置為 "D:\C# Projects\MyApplication.exe" "%1",只要當中包含標示符“%1”,應用程序可以根據自定義協議的路徑獲取對應的參數,其使用方式將在下面的章節再詳細說明。
簡單測試:建立一個HTML頁面,如入以下代碼。
注意:此連接路徑正是以注冊表產首項的MyApplication名稱相同。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> ...... </head> <body> <a href="MyApplication://command">Hello World</a> </body> </html>
當按下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 添加安裝項目
然後在解決方案裡面添加一個“安裝項目”
右鍵點擊"安裝項目",選擇“視圖-文件系統”後,在應用程序文件夾中添加當前的“MyApplication”項目。
4.3 修改注冊表
右鍵點擊"安裝項目",選擇“視圖-注冊表”後,按照第三節的例子在HKEY_CLASSES_ROOT上建立多個必要項。為方法獲取此應用程序的安裝路徑,可以在MyApplication項中加入一個鍵值Path,綁定"[TARGETDIR]",便於系統隨時能通過此鍵值獲取應用程序的安裝路徑。
在“安裝項目”中有多個可用的綁定值,例如:“[TARGETDIR]”用於綁定應用程序的安裝路徑,“[Manufacturer]”用於綁定應用程序制造商名稱等等。在command的值中輸入"[TARGETDIR]MyApplication.exe""%1",系統成功安裝後,此值就會轉換成應用程序的安裝路徑。例如:MyApplication應用程序安裝在"D:\C# Projects"安件夾中,那麼注冊表的command默認值就會變成“D:\C# Projects\MyApplication.exe” “%1”。
4.4 添加安裝自定義操作
在安裝應用程序的前後,很多時候需要做一些必要的操作,例如存儲程序的Path值,為應用程序生成一個sn文件作為標識等等。這時候就可以通過建立Installer的子類,在安裝的前後的事件進行操作。
首先建立新項目InstallComponent,在項目中加入一個具備RunInstaller特性的類繼承Installer類,RunInstaller特性是作用是用於指示在程序集安裝期間是否調用該安裝程序。而Installer類是Framework 中所有自定義安裝程序的基類,它具備了以下多個方法。
Installer方法表4.4.1
只要自定義的類型繼承了Installer類並重寫 Install、Commit、Rollback 和 Uninstall 等方法,系統就可以在應用程序安裝的多個不同狀態下進行操作。下面這個常用例子當中,MyInstaller加入了AfterInstall事件的處理方法,在MyApplication應用程序安裝完成後,會根據注冊表的Path鍵值獲取應用程序的安裝路徑,並在該文件夾內加入sn文件。sn文件內存儲著一個GUID,作為該應用程序的一個標識。
[RunInstaller(true)] public partial class MyInstaller : Installer { public MyInstaller() : base() { //綁定完成安裝事件的處理方法 this.AfterInstall += new InstallEventHandler(OnAfterInstall); } /// 加入安裝完成後的處理方法 protected override void OnAfterInstall(object sender, InstallEventArgs e) { CreateSn(); } //在完成安裝後建立一個sn文件,對該應用程序進行標識 private void CreateSn() { var regKey = Registry.ClassesRoot.OpenSubKey("MyApplication", true); if (regKey != null) { //根據注冊表中的Path鍵值,獲取系統在客戶端的安裝路徑 string path = regKey.GetValue("Path").ToString(); //建立sn文件 string snPath = path + "sn"; StreamWriter writer = new StreamWriter(snPath, true, Encoding.Unicode); writer.Write(Guid.NewGuid().ToString()); writer.Close(); } } /// 重寫安裝過程方法 public override void Install(IDictionary stateSaver) { base.Install(stateSaver); } /// 重寫卸載方法 public override void Uninstall(IDictionary savedState) { base.Uninstall(savedState); } /// 重寫回滾方法 public override void Rollback(IDictionary savedState) { base.Rollback(savedState); } //重寫提交方法 public override void Commit(IDictionary savedState) { base.Commit(savedState); } }
4.5 在安裝項目中綁定自定義操作
當完成自定義操作的設定後,回到安裝項目,右鍵點擊"安裝項目",選擇“視圖-文件系統”後,在應用程序文件夾中添加自定義操作的“InstallComponent”項目。
然後右鍵點擊"安裝項目",選擇“視圖-自定義操作-添加自定義操作-應用程序文件夾”,選擇剛才導入的 “InstallComponent”項目。
把安裝、提交、回滾、卸載等操作都與InstallComponent的MyInstaller類進行綁定。
生成安裝項目後,點擊setup應用程序進行系統安裝,完成安裝後你就會發現在注冊表的HKEY_CLASSES_ROOT下將添加了MyApplication項。而且在該應用程序文件夾中會自動增加一個sn文件,裡面將保存著一個CUID碼。
回到目錄
五、自定義協議的調用
5.1 以連接方式調用
調用自定義協議的方式很多,其中最簡單的就是以連接方式來調用,好像下面的例子,當頁面連接地址為MyApplication://自定義協議時,系統就會自動到注冊表查找該協議,根據command默認項的綁定路徑對該程序進行調用。並把“MyApplication://command&{'ID':'1','Name':'Rose','Age':'26'}" 路徑名作為static void main(string[] args) 方法中的其中一個參數輸入。
<body> <script type="text/javascript"> window.onload = function () { var link = "MyApplication://command&{'ID':'1','Name':'Rose','Age':'26'}"; location.href = link; } </script> </body>
觀察第4節的內容,自定義協議的main方法會把args[0]參數按照字符'&'進行分組,然後把後面的"{'ID':'1','Name':'Rose','Age':'26'}"JSON字符串轉換成Person對象進行顯示。
5.2 動態調用
回顧前面例子,一直都是運用最簡單的連接方式對自定義協議進行調用。然而在現實的開展過程中,這種方法並不可行,因為每次調用客戶端的自定義協議可能需要不同的參數,把參數直接通過連接路徑來傳輸具有安全性問題。
最簡單的解決方案是把自定義協議的路徑在IHttpHandler裡面生成,再通過ajax來獲取,在回調函數中再調用此協議。通過此方法,協議的路徑不會以文本的方式存在於客戶端。除非是熟悉開發人員通過測試工具進行逐步檢索,否則一般人不能通過頁面找到自定義協議信息。
下面就是一個以IHttpHandler生成自定義協議的一個例子,MyHandler會根據url路徑獲取請求對象的id值,然後進行數據查詢,並把查詢到的對象轉化為JSON格式。最後把自定義協議的路徑返回到客戶端。
[DataContract] public class Person { public Person(int id, string name, int age) { ID = id; Name = name; Age = age; } [DataMember] public int ID; [DataMember] public string Name; [DataMember] public int Age; } public class MyHandler : IHttpHandler { public bool IsReusable { get { return true; } } public void ProcessRequest(HttpContext context) { //通過QueryString獲取id string data = context.Request.QueryString["id"]; if (data != null) { int id = int.Parse(data); //根據id進行數據查找 foreach (var person in DataSource()) { if (person.ID == id) { //把Person對象轉化為JSON數據 string json = ConvertToJson(person); //輸出自定義協議路徑 context.Response.Write(GetUrl(json)); } } } } //獲取自定義協議路徑 private string GetUrl(string json) { return "MyApplication://command&" + json; } //把Person對象轉化為JSON private string ConvertToJson(Person person) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Person)); MemoryStream stream = new MemoryStream(); serializer.WriteObject(stream, person); byte[] bytes = stream.ToArray(); stream.Close(); return Encoding.ASCII.GetString(bytes); } //模擬數據源 private IList<Person> DataSource() { IList<Person> list = new List<Person>(); Person person1 = new Person(1, "Rose", 34); list.Add(person1); ...... return list; } }
客戶端通過ajax把id發送到MyHandler.ashx進行查詢,在回調函數中調用所獲取到的自定義協議。
如果自定義協議參數中具有保密資料的信息還可以通過加密方式進行傳遞,好像上面的一個例子,客戶端可以先把自動生成的sn發送到服務器進行記錄,並與客戶ID進行綁定。在請求自定義協議的路徑時通過IHttpHandler把相關的信息通過sn進行加密,等到數據發送到客戶端後再進行解密。
<head> <title></title> <script src="Scripts/jquery-1.8.2.min.js" type="text/javascript"></script> </head> <body> <a name="send" id="send" href="#">GetPerson</a> <script type="text/javascript"> $(function () { $('#send').click(function () { $.ajax({ type: "GET", url: "MyHandler.ashx?id=1", data: null, dataType: null, success: function (data) { location.href = data; } }); }); }); </script> </body> </html>
回到目錄
本章小結
自定義協議有著廣泛的應用,像QQ、迅雷、淘寶等等這些的常見的應用程序都會使用自定義協議。特別在大型的企業系統開發過程中,C/S、B/S融合開發的情況很常見,這時候自定義協議更發揮其獨特的作用。一般在系統自動更新,客戶端信息獲取等這些功能上都會使用自定義協議進行開發。相對於ActiveX控件,自定義協議不會受到浏覽器的約束,更能簡化客戶端與浏覽器之間的信息傳信。
對 .NET 開發有興趣的朋友歡迎加入QQ群:230564952 共同探討 !
C#綜合揭秘
通過修改注冊表建立Windows自定義協議
Entity Framework 並發處理詳解
細說進程、應用程序域與上下文
細說多線程(上)
細說多線程(下)
細說事務
深入分析委托與事件
作者:風塵浪子
http://www.cnblogs.com/leslies2/p/3727762.html
原創作品,轉載時請注明作者及出處