通過修改註冊表建立Windows自定義協議

来源:https://www.cnblogs.com/lvjy-net/archive/2018/01/18/8310342.html
-Advertisement-
Play Games

引言 本文主要介紹註冊表的概念與其相關根項的功能,以及瀏覽器如何通過連接調用自定義協議並與客戶端進行數據通信。文中講及如何通過C#程式、手動修改、安裝項目等不同方式對註冊表進行修改。其中通過安裝項目對註冊表進行修改的情況最為常見,在一般的應用程式中都會涉及。當中最為實用的例子將介紹如何通過"安裝項目 ...


引言

本文主要介紹註冊表的概念與其相關根項的功能,以及瀏覽器如何通過連接調用自定義協議並與客戶端進行數據通信。文中講及如何通過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名稱相同。

複製代碼
<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 中所有自定義安裝程式的基類,它具備了以下多個方法。    

方法說明
Commit 在派生類中重寫時,完成安裝事務。
Install 在派生類中被重寫時,執行安裝。
OnAfterInstall 引發 AfterInstall 事件。
OnAfterRollback 引發 AfterRollback 事件。
OnAfterUninstall 引發 AfterUninstall 事件。
OnBeforeInstall 引發 BeforeInstall 事件。
OnBeforeRollback 引發 BeforeRollback 事件。
OnBeforeUninstall 引發 BeforeUninstall 事件。
OnCommitted 引發 Committed 事件。
OnCommitting 引發 Committing 事件。
Rollback 在派生類中重寫時,還原電腦的安裝前狀態。
Uninstall 在派生類中重寫時,移除安裝。

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控制項,自定義協議不會受到瀏覽器的約束,更能簡化客戶端與瀏覽器之間的信息傳信。

轉載於http://www.cnblogs.com/leslies2/p/3727762.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;u ...
  • 這是從上文的<<圖文並茂的生產者消費者應用實例demo>>整理總結出來的,具體就不說了,直接給出代碼,註釋我已經加了,原來的code請看<<.Net中的並行編程-7.基於BlockingCollection實現高性能非同步隊列>>,我改成適合我的版本了,直接給code: 調用code: 封裝的隊列: ...
  • 前幾步和網上其他教程一樣的。主要是把.net framework 打包進安裝程式里,如果選的是“從與我的應用程式相同的位置下載系統必備組件”,會提示 ERROR: 要在“系統必備”對話框中啟用“從與我的應用程式相同的位置下載系統必備組件”,必須將“Microsoft .NET Framework 4 ...
  • 首先本地得有網路 運行 "cmd"命令: 輸入"ipconfig": 拿到自己的IP地址 將要測試的項目在iis中配置好 index.aspx是首頁,也就是二維碼頁面 生成二維碼(index.aspx.cs頁面,基於QRCoder生成): 掃描生成的二維碼就自動跳到要測試的頁面了 ...
  • 上一篇講解了拼團提醒邏輯功能實現,現在繼續實現頁面功能。 Core項目 打開AbpZeroTemplate-zh-CN.xml語言文件,在末尾添加如下代碼: 文件路徑:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyNa ...
  • 在 Asp.net SignalR 讓實時通訊變得簡單 中思明分享了一個直接寄宿到IIS上的SignalR,SignalR同時也可以宿主在任何應用程式,包括控制台,客戶端程式和Windows服務等,另外還支持Mono,這意味著它可以實現跨平臺部署在Linux環境下。 在我參考的博文 [Asp.net ...
  • 準備工作 想要使用Wix,首先需要去官網下載Wixtoolset。下載安裝之後,啟動visual studio,新建項目,可以看到在左邊的菜單欄多出了(Windows Installer XML)選項。 使用的工具:visual studio 2010 Wix版本號(WiX v3.7 (Stable ...
  • 文檔合併是一種高效文檔處理方式。如果能夠有一個方法能將多種不同類型的文檔合併成一種文檔格式,那麼在文檔存儲管理上將為我們提供極大的便利。因此,本篇文章介紹了一種如何使用免費組件Free Spire.Office for .NET來實現將多種各式的文檔合併為PDF的方法。本方法中可合併的文檔格式可以是 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...