摘 要:
本文針對目前C/S模式下編寫的應用程式可維護性差的特點,提出了一套自動線上升級的解決方案,分析了線上升級的困難及實現原理,並給出了實現升級的部分代碼,具有實際參考價值和現實意義。本文程式碼均在 Framework 1.1 和2000下測試通過。
關鍵詞:;線上升級;自動升級;;XML文檔
1 前言
長期以來,廣大程式員為到底是使用Client/Server,還是使用Browser/Server結構爭論不休,在這些爭論當中,C/S結構的程式可維護性差,布置困難,升級不方便,維護成本高就是一個相當重要的因素。有很多企業使用者就是因為這個原因而放棄使用C/S。然而當一個應用必須要使用C/S結構才能很好的實現其功能的時候,我們該如何解決用戶端的部署與自動升級問題?部署很簡單,只要點擊安裝程式即可,難的在於每當有新版本發布時,能夠實現自動升級[3]。現在好了,我們的目標很簡單,我們希望開發一個與具體應用無關的能夠複用的自動升級系統。下面我為大家提供了一套可複用的用編寫的自動升級系統。
2 實現軟體的自動升級存在的困難
第一,為了尋找遠程上的更新,應用程式必須有查詢網路的途徑,這需要網路編程、簡單的應用程式與通訊的。
第二是。看起來不需要考慮連網的問題,但要考慮下載使用者請求的檔案,以及在沒有使用者同意時下載大檔案。友好的自動更新應用程式將使用剩餘的頻寬下載更新。這聽起來簡單,但卻是一個技術難題,幸運的是已經有瞭解決方法。
第三個考慮因素是使用新版應用程式更換原應用程式的過程。這個問題比較有趣,因為它要求代碼運行時將自己從系統刪除,有多種辦法可以實現該功能[5],本文程式主要通過比較新舊版本的日期號來實現替換新版本應用程式的功能。
3 實現軟體自動線上升級的原理
寫兩個程式,一個是主程式;一個是升級程式;所有升級任務都由升級程式完成。
1.啟動升級程式,升級程式串連到網站,下載新的主程式(當然還包括支援的庫檔案、XML配置文檔等)到臨時檔案夾;
2.升級程式擷取伺服器端XML設定檔中新版本程式的更新日期或版本號碼或檔案大小;
3.升級程式擷取原有用戶端應用程式的最近一次更新日期或版本號碼或檔案大小,兩者進行比較;如果發現升級程式的日期大於原有程式的最新日期,則提示使用者是否升級;或者是採用將現有版本與最新版本作比較,發現最新的則提示使用者是否升級;也有人用其它屬性如檔案大小進行比較,發現升級程式的檔案大小大於舊版本的程式的大小則提示使用者升級。本文主要採用比較新舊版本更新日期號來提示使用者升級。
4.如果使用者選擇升級,則擷取下載檔案清單,開始進行批量下載文檔;
5.升級程式檢測舊的主程式是否活動,若活動則關閉舊的主程式;
6.刪除舊的主程式,拷貝臨時檔案夾中的檔案到相應的位置;
7.檢查主程式的狀態,若狀態為活動的,則啟動新的主程式;
8.關閉升級程式,升級完成[4]。
4 用實現線上升級的關鍵步驟
這裡我主要使用日期資訊來檢測是否需要下載升級版本。
4.1 準備一個XML設定檔
名稱為AutoUpdater.xml,作用是作為一個升級用的模板,顯示需要升級的資訊。
<?xml version="1.0"?> //xml版本號碼 <AutoUpdater> <URLAddres URL="http://192.168.198.113/vbroker/log/"/>//升級檔案所在伺服器端的網址 <UpdateInfo> <UpdateTime Date = "2005-02-02"/> //升級檔案的更新日期 <Version Num = "1.0.0.1"/> //升級檔案的版本號碼 </UpdateInfo> <UpdateFileList> //升級檔案清單 <UpdateFile FileName = "aa.txt"/> //共有三個檔案需升級 <UpdateFile FileName = "VB40.rar"/> <UpdateFile FileName = "VB4-1.CAB"/> </UpdateFileList> <RestartApp> <ReStart Allow = "Yes"/> //允許重新啟動應用程式 <AppName Name = "TIMS.exe"/> //啟動的應用程式名稱 </RestartApp> </AutoUpdater> |
從以上XML文檔中可以得知升級文檔所在伺服器端的地址、升級文檔的更新日期、需要升級的檔案清單,其中共有三個檔案需升級:aa.txt、VB40.rar、VB4-1.CAB。以及是否允許重新啟動應用程式和重新啟動的應用程式名稱。
4.2 擷取用戶端應用程式及伺服器端升級程式的最近一次更新日期
通過GetTheLastUpdateTime()函數來實現。
private string GetTheLastUpdateTime(string Dir) { string LastUpdateTime = ""; string AutoUpdaterFileName = Dir + @"\AutoUpdater.xml"; if(!File.Exists(AutoUpdaterFileName)) return LastUpdateTime; //開啟xml檔案 FileStream myFile = new FileStream(AutoUpdaterFileName,FileMode.Open); //xml檔案閱讀器 XmlTextReader xml = new XmlTextReader(myFile); while(xml.Read()) { if(xml.Name == "UpdateTime") { //擷取升級文檔的最後一次更新日期 LastUpdateTime = xml.GetAttribute("Date"); break; } } xml.Close(); myFile.Close(); return LastUpdateTime; } |
通過XmlTextReader開啟XML文檔,讀取更新時間從而擷取Date對應的值,即伺服器端升級檔案的最近一次更新時間。
函數調用實現:
//擷取用戶端指定路徑下的應用程式最近一次更新時間
string thePreUpdateDate = GetTheLastUpdateTime(Application.StartupPath);
Application.StartupPath指用戶端應用程式所在的路徑。
//獲得從伺服器端已下載文檔的最近一次更新日期
string theLastsUpdateDate = GetTheLastUpdateTime(theFolder.FullName);
theFolder.FullName指在升級文檔下載到客戶機上的臨時檔案夾所在的路徑。
4.3 比較日期
用戶端應用程式最近一次更新日期與伺服器端升級程式的最近一次更新日期進行比較。
//獲得已下載文檔的最近一次更新日期 string theLastsUpdateDate = GetTheLastUpdateTime(theFolder.FullName); if(thePreUpdateDate != "") { //如果用戶端將升級的應用程式的更新日期大於伺服器端升級的應用程式的更新日期 if(Convert.ToDateTime(thePreUpdateDate)>=Convert.ToDateTime(theLastsUpdateDate)) { MessageBox.Show("當前軟體已經是最新的,無需更新!","系統提示",MessageBoxButtons.OK,MessageBoxIcon.Information); this.Close(); } } this.labDownFile.Text = "下載更新檔案"; this.labFileName.Refresh(); this.btnCancel.Enabled = true; this.progressBar.Position = 0; this.progressBarTotal.Position = 0; this.progressBarTotal.Refresh(); this.progressBar.Refresh(); //通過動態數組擷取下載檔案的列表 ArrayList List = GetDownFileList(GetTheUpdateURL(),theFolder.FullName); string[] urls = new string[List.Count]; List.CopyTo(urls, 0); |
將用戶端升級的應用程式的日期與伺服器端下載的應用程式日期進行比較,如果前者大於後者,則不更新;如果前者小於後者,則通過動態數組擷取下載檔案的列表,開始下載檔案。