對於PC桌面應用程序而言,自己主動升級功能往往是不可缺少的。
而自己主動升級能夠作為一個獨立的C/S系統來開發,這樣,就能夠在不同的桌面應用中進行復用。本文將着重介紹OAUS的相關背景、用法,至於具體的實現細節,大家能夠直接下載源代碼研究。
假設了解了OAUS的使用。源代碼的理解就非常easy了。
假設須要直接部署使用自己主動升級系統,那么,可下載文末的可執行程序壓縮包。
一.OAUS的主要功能
眼下主流的程序自己主動升級策略是,又一次下載最新的安裝包,然后又一次安裝整個client。
這種方式盡管簡單直觀,可是缺陷也非常明顯。比方,即使整個client有100M。而本次更新僅僅僅僅是改動了一個1k大小的dll,那也意味着要又一次下載100M的所有內容。
這對帶寬是極大的浪費,並且延長了升級了時間,相應地也添加了客戶茫然等待的時間。
在上述的場景中,自己主動升級時,我們是否能僅僅更新那個被改動了的1k的dll了?當然,使用OAUS自己主動升級系統能夠輕松地做到這一點。OAUS自己主動升級系統能夠對被分發的client程序中的每一個文件進行版本號管理,每次升級的基礎單元不再是整個client程序,而是當中的單個文件。
針對單個文件的更新,包含三種形式:
(1)文件被改動。
(2)文件被刪除。
(3)新添加某個文件。
OAUS對這三種形式的文件更新都是支持的。每次自己主動升級,都能夠更改N個文件、刪除M個文件、新添加L個文件。
二.OAUS的使用
1.OAUS的結構
OAUS提供了可直接執行的服務端程序和client程序:AutoUpdaterSystem.Server.exe 和 AutoUpdater.exe。 OAUS服務端的目錄結構例如以下所看到的:
OAUS的client與server之間通過TCP通信,能夠在AutoUpdaterSystem.Server.exe.config配置文件里配置server通過哪個TCPport提供自己主動升級服務。
FileFolder目錄初始是空的。其用於部署被分發的程序的各個文件的最新版本號。
注意。其下的文件結構一定要與被分發的程序正常部署后的結構全然一致 -- 即相當於在FileFolder目錄下部署一個被分發的程序。
OAUSclient的目錄結構例如以下:
能夠在AutoUpdater.exe.config配置文件里配置OAUSserver的IP、port等信息。其內容例如以下所看到的:
<configuration>
<appSettings>
<!--serverIP -->
<add key="ServerIP" value="127.0.0.1"/>
<!--serverport-->
<add key="ServerPort" value="4530"/>
<!--升級完畢后。將被回調的可執行程序的名稱-->
<add key="CallbackExeName" value="Demo.exe"/>
<!--主窗口的Title-->
<add key="Title" value="文件更新"/>
</appSettings>
</configuration>
請注意配置的CallbackExeName,其表示當升級完畢之后。將被啟動的分發程序的exe的名稱。
這個CallbackExeName配置的為什么是名稱而不是路徑了?這是由於使用和部署OAUSclient時是有要求的:
(1)被分發的程序的可執行文件exe必須位於部署目錄的根目錄。
(2)OAUS的client(即整個AutoUpdater目錄)也必須位於這個根目錄。
如此,AutoUpdater就知道分發程序的exe相對自己的路徑,如此就能夠確定分發程序的exe的絕對路徑,所以就能夠在升級完畢后啟動目標exe了。另外,依據上述的兩個約定,再結合前面講到的服務端的FileFolder目錄的結構約定,當服務端更新一個文件時,AutoUpdater便能夠確定該文件在client機器上的絕對路徑了。
2. OAUS自己主動升級流程
以下我們就具體講講怎樣使用OAUS來構建自己主動升級系統,大概的過程例如以下。
(1)執行OAUS服務端。
(2)將被分發的client程序的所有內容放到OAUS服務端的FileFolder目錄下。其結構與client程序正常部署后的結構要全然一致。我們以部署VideoChatSystem為例。
(3)使用OAUS服務端為被分發的client程序的每一個文件生成默認版本號號,並創建版本號信息配置文件UpdateConfiguration.xml。這個配置文件也將被client使用。
點擊服務端界面上的“文件版本號管理”button,將彈出用於管理各個文件版本號的【文件版本號信息】窗口。
當用新版本號的文件覆蓋老的文件后,點擊“自己主動掃描”button,服務端就會檢索FileFolder目錄下文件的名稱、大小、最后更新時間,然后得出本次更新結果:變化了幾個文件、新增了幾個文件、刪除了幾個文件。 自己主動掃描功能把之前的手動操作所有簡化了。
假設須要手動操作,能夠這樣做:
雙擊列表中的隨意一行,能夠改動其相應文件的版本號的值(int類型的數值)。
注意,此列表中的版本號信息與文件的真實版本號屬性(比方dll的版本號屬性X.X.X.X)能夠是沒有不論什么聯系的,列表中版本號的值僅僅是用於標記文件是否被改動。所以,文件每被改動一次,其列表中相應的版本號的值就應該有所增大。
當關閉【文件版本號信息】窗口時。僅僅要有某個文件版本號變化。則“最后綜合版本號”的值(int類型)會遞增1。通過比較OAUS的client保存的“最后綜合版本號”的值與OAUS的服務端最新的“最后綜合版本號”的值,就能夠高速地識別client是否已經是最新版本號了。
另外,初次打開這個窗口時,將在OAUS服務端的目錄下,自己主動生成一個版本號信息配置文件UpdateConfiguration.xml。並且。每當通過該窗口來設置某個文件的新版本號時,UpdateConfiguration.xml會自己主動同步更新。
(4)將UpdateConfiguration.xml加入到OAUS的client程序(即上述的AutoUpdater的目錄)中。
(5)在創建被分發的client的安裝程序時。將OAUS的client(即AutoUpdater的目錄)也打包進去,並且像前面說的一樣,要將其直接部署在執行目錄(BaseDirectory)下(與分發的exe同一目錄)。
如此,准備工作就完畢了,當client通過安裝包安裝好了VideoChatSystem之后。其目錄結構像以下這樣:
(6)當我們有新的版本號要公布時。比方要更新某個文件(由於文件被改動),那么能夠這樣做:
a.將改動后的文件復制到OAUS服務端的FileFolder目錄下的正確位置(或覆蓋舊的文件)。
b.在OAUS服務端打開【文件版本號信息】窗口,雙擊被改動文件所相應的Row。在彈出的窗口上改動相應文件的版本號號,將版本號號的數值添加。(假設是刪除舊文件或加入新文件,此處也可進行相應的操作)
(7)如此,當client再啟動AutoUpdater.exe時,就會自己主動升級。更新那些發生變化的文件。 以下是AutoUpdater.exe執行起來后的截圖。
(8)當升級完畢后,將啟動前述的OAUSclient配置文件里配置的回調exe。(在本例中就是VideoChatSystem.exe)
(9)OAUSclient會在日志文件UpdateLog.txt(位於AutoUpdater的目錄下。在OAUSclient首次執行時自己主動生成該文件)中。記錄每次自己主動升級的情況。
(10)假設升級的過程中。與服務端連接中斷,則會自己主動重連。在重連成功后,將啟動斷點續傳。
3.何時啟動自己主動升級client?
假設某個系統是下載client形式的,那么client該怎樣知道是否有新版本號了?然后又該何時啟動AutoUpdater.exe了?
我們的經驗是這種:client登錄成功之后,從server獲取“最后綜合版本號”的值。然后與本地的“最后綜合版本號”的值相比較,假設本地的值較小,則表示client須要更新。這個過程能夠這樣做到:
(1)當在OAUS服務端的FileFolder目錄下放置了新的文件。並通過【文件版本號信息】窗口正確的更新了版本號號,在關閉【文件版本號信息】窗口時,“最后綜合版本號”的值會自己主動加1。
(2)系統client能夠通過調用OAUS.Core.VersionHelper類的靜態方法HasNewVersion()來推斷是否有新版本號。
(3)假設HasNewVersion方法返回true,則通常有兩種模式:由用戶選擇是否升級。或者是強制升級。
一般而言,假設最新client程序與老版本號兼容,不升級也影響不大,則能夠交由用戶決定是否升級。假設最新client程序不兼容老版本號,或者是有重大更新,則將啟動強制升級。假設流程要進入啟動升級,那么僅僅要啟動AutoUpdater的目錄下AutoUpdater.exe就能夠了。要注意的是,啟動AutoUpdater.exe進程后。要退出當前的client進程,否則,有些文件會由於無法被覆蓋而導致更新失敗。代碼大致例如以下所看到的:
if (VersionHelper.HasNewVersion(oausServerIP,oausServerPort)) { string updateExePath = AppDomain.CurrentDomain.BaseDirectory + "AutoUpdater\\AutoUpdater.exe"; System.Diagnostics.Process myProcess = System.Diagnostics.Process.Start(updateExePath); ......//退出當前進程
}