软件更新原理
自動更新的時候,客戶端軟件提交更新請求給固定的網址,然后網址返回最新版本的版本號。客戶端 軟件和自己的版本號對比,如果發現服務器的版本和自己的版本不一樣,那么就請求下載升級補丁。服務 器響應請求,提供補丁下載;下載成功后,手動或自動安裝一下就可以了。 安裝補丁的時候,客戶端的主程序一般是要關閉的,除非采用動態卸載、調入組件的技術,比如網絡 游戲,就是盡量讓玩家邊玩游戲邊更新。 如果更新的是主程序,那么就必須關閉主程序了。可是主程序關閉了之后,誰來調用安裝補丁呢?為 了解決這個問題,人們把主程序和自動更新程序分開來做。當需要校驗版本的時候,主程序調用自動更新 程序。自動更新程序如果發現主程序需要更新,在下載了升級補丁之后,就會要求關閉主程序。主程序關 閉之后,自動更新程序調用升級補丁進行安裝,安裝完成后再重新啟動主程序。自動更新程序自動退出, 完成更新任務。這和你剛才關閉電腦后再插網卡的原理是一模一樣的。其實生活中有很多現象可以借鑒到 軟件設計中。 人們嫌這樣的升級仍然太麻煩,后來出現了B/S結構,大家像抓住了救命稻草一樣的追捧至今,希望 能從這些勞動中解脫出來。B/S結構就是瀏覽器/服務器結構,它所有的功能,都是在瀏覽器里完成。程序 升級的時候,只需要在服務端升級一下就可以了,瀏覽器再次訪問服務器的時候,得到的就是新版本。你 可以把它理解成一個純粹的網站。是不是站長更新的時候,你打開網站就看到最新的頁面? 但是B/S結構有天生的弱點,因為它是基于網頁瀏覽的,所以安全性是首要的難題,你能瀏覽的東西, 原則上別人也能瀏覽。而且出于安全考慮,B/S訪問本地資源,比如串口,必須借助于其他技術實現。B/S 也不是萬能的,必須考慮實際應用。 Winform的自動更新 winform程序相對web程序而言,功能更強大,編程更方便,但軟件更新卻相當麻煩,要到客戶端一臺一 臺地升級,面對這個實際問題,在最近的一個小項目中,本人設計了一個通過軟件實現自動升級技術方案, 彌補了這一缺陷,有較好的參考價值。 一、升級的好處。 長期以來,廣大程序員為到底是使用Client/Server,還是使用Browser/Server結構爭論不休,在這些爭論 當中,C/S結構的程序的可維護性差,布置困難,升級不方便,維護成本高就是一個相當重要的因素,也是 那些B/S的支持者們將Client/Server結構打入地獄的一個重要原因。 現在好了,我們就在最新的基于Microsoft的WinForm上用WebServices來實現軟件的自動升級功能。 二、升級的技術原理。 升級的原理有好幾個,首先無非是將現有版本與最新版本作比較,發現最新的則提示用戶是否升級。當然 也有人用其它屬性比較的,例如:文件大小。 或者更新日期。 而實現的方法呢?在VB時代,我使用的是XmlHTTP+INet控件。用XmlHTTP獲取信息,用INET傳輸升 級文件,而用一個簡單的BAT文件來實現升級。 PublicSubCheckUpdate() OnErrorResumeNext DimbAsBoolean DimXmlHttpAsObject SetXmlHttp=CreateObject("Microsoft.XMLHttp" XmlHttp.Open"GET","Http://mu.5inet.net/MuAdmin/update.xml",False XmlHttp.Send DimvsAsString vs=XmlHttp.responseText IfErr.Number>0Then ExitSub EndIf DimXmlAsObject SetXml=CreateObject("Microsoft.XmlDom" Xml.LoadXmlvs DimVersionAsString DimdownAddrAsString DimFSizeAsLong DimfInfoAsString Version=Xml.DocumentElement.ChildNodes(0).Text downAddr=Xml.DocumentElement.ChildNodes(1).Text FSize=CLng(Xml.DocumentElement.ChildNodes(2).Text) fInfo=Xml.DocumentElement.ChildNodes(3).Text SetXml=Nothing SetXmlHttp=Nothing DimMajorAsLong DimMinorAsLong DimRevisionAsLong DimC()AsString C=Split(Version,"." Major=CLng(C(0)) Minor=CLng(C(1)) Revision=CLng(C(2)) IfMajor>App.MajorThen b=True ElseIfMinor>App.MinorThen b=True ElseIfRevision>App.RevisionThen b=True Else b=False EndIf If(b)Then DimresultAsVbMsgBoxResult result=MsgBox("發現程序新版本。當前版本為:"&App.Major&"."&App.Minor&"."&App.Revision& ",目前最新版本為:"&Version&",是否進行更新?",vbQuestionOrvbYesNo,"自動更新" Ifresult=vbYesThen DimfrmAsNewUpdate frm.DownloadAddress=downAddr frm.size=FSize frm.InfoPage=fInfo frm.Version=Version frm.Show vbModal EndIf EndIf EndSub 而BAT文件有個特性,是可以刪除自己本身。下面是BAT文件的內容. @echooff echo echoecho歡迎使用無垠奇跡管理器升級向導。 echo本次升級版本為:1.1.0。 echo請按任意鍵開始升級無垠奇跡管理器...echo echo pause delSQLSrvBrowser.Exe ren~update.tmpSQLSrvBrowser.Exe echo升級成功,按任意鍵重新啟動應用程序。 pause start http://mu.5inet.net/ startSQLSrvBrowser.Exe delupdate.bat 三、在.Net時代的實現。 在.Net時代,我們就有了更多的選擇,可以使用WebRequest,也可以使用WebServices。在這里我們將用 WebServices來實現軟件的自動升級。 實現原理:在WebServices中實現一個GetVer的WebMethod方法,其作用是獲取當前的最新版本。 然后將現在版本與最新版本比較,如果有新版本,則進行升級。 步驟: 1、準備一個XML文件(Update.xml)。 <?xmlversion="1.0"encoding="utf-8"?> <product> <version>1.0.1818.42821</version> <description>修正一些Bug</description> <filelistcount="4"sourcepath="./update/"> <itemname="City.xml"size=""> <value/> </item> <itemname="CustomerApplication.exe"size=""> <value/> </item> <itemname="Interop.SHDocVw.dll"size=""> <value/> </item> <itemname="Citys.xml"size=""> <value/> </item> </filelist> </product> 作用是作為一個升級用的模板。 2、WebServices的GetVer方法。 [WebMethod(Description="取得更新版本"] publicstringGetVer() { XmlDocumentdoc=newXmlDocument(); doc.Load(Server.MapPath("update.xml"); XmlElementroot=doc.DocumentElement; returnroot.SelectSingleNode("version".InnerText; } 3、WebServices的GetUpdateData方法。 [WebMethod(Description="在線更新軟件"] [SoapHeader("sHeader"] publicSystem.Xml.XmlDocumentGetUpdateData() { //驗證用戶是否登陸 if(sHeader==null) returnnull; if(!DataProvider.GetInstance.CheckLogin(sHeader.Username,sHeader.Password)) returnnull; //取得更新的xml模板內容 XmlDocumentdoc=newXmlDocument(); doc.Load(Server.MapPath("update.xml"); XmlElementroot=doc.DocumentElement; //看看有幾個文件需要更新 XmlNodeupdateNode=root.SelectSingleNode("filelist"; stringpath=updateNode.Attributes["sourcepath"].Value; int count=int.Parse(updateNode.Attributes["count"].Value); //將xml中的value用實際內容替換 for(inti=0;i<count;i++) { XmlNodeitemNode =updateNode.ChildNodes[i]; stringfileName=path+itemNode.Attributes["name"].Value; FileStreamfs=File.OpenRead(Server.MapPath(fileName)); itemNode.Attributes["size"].Value =fs.Length.ToString(); BinaryReaderbr=newBinaryReader(fs); //這里是文件的實際內容,使用了Base64String編碼 itemNode.SelectSingleNode("value".InnerText = Convert.ToBase64String(br.ReadBytes((int)fs.Length),0,(int)fs.Length); br.Close(); fs.Close(); } returndoc; } 4、在客戶端進行的工作。 首先引用此WebServices,例如命名為:WebSvs, stringnVer=Start.GetService.GetVer(); if(Application.ProductVersion.CompareTo(nVer)<=0) update(); 在本代碼中Start.GetService是WebSvs的一個Static實例。首先檢查版本,將結果與當前版本進行比較, 如果為新版本則執行UpDate方法。voidupdate() { this.statusBarPanel1.Text="正在下載..."; System.Xml.XmlDocumentdoc=((System.Xml.XmlDocument)Start.GetService.GetUpdateData()); doc.Save(Application.StartupPath+@"update.xml"; System.Diagnostics.Process.Start(Application.StartupPath+@"update.exe"; Close(); Application.Exit(); }這里為了簡單起見,沒有使用異步方法,當然使用異步方法能更好的提高客戶體驗,這個需要讀者們自己 去添加。:)update的作用是將升級的XML文件下載下來,保存為執行文件目錄下的一個Update.xml文 件。任務完成,退出程序,等待Update.Exe來進行升級。 5、Update.Exe的內容。privatevoidForm1_Load(objectsender,System.EventArgse) { System.Diagnostics.Process[]ps=System.Diagnostics.Process.GetProcesses(); foreach(System.Diagnostics.Processpin ps) { //MessageBox.Show(p.ProcessName); if(p.ProcessName.ToLower()=="customerapplication" { p.Kill(); break; } } XmlDocumentdoc=newXmlDocument(); doc.Load(Application.StartupPath+@"update.xml"; XmlElementroot=doc.DocumentElement; XmlNodeupdateNode=root.SelectSingleNode("filelist"; stringpath=updateNode.Attributes["sourcepath"].Value; int count=int.Parse(updateNode.Attributes["count"].Value); for(inti=0;i<count;i++) { XmlNodeitemNode =updateNode.ChildNodes[i]; stringfileName=itemNode.Attributes["name"].Value; FileInfofi=newFileInfo(fileName); fi.Delete(); //File.Delete(Application.StartupPath+@""+fileName); this.label1.Text="正在更新:"+fileName+"("+itemNode.Attributes["size"].Value +"..."; FileStreamfs=File.Open(fileName,FileMode.Create,FileAccess.Write); fs.Write(System.Convert.FromBase64String(itemNode.SelectSingleNode("value" .InnerText),0,int.Parse (itemNode.Attributes["size"].Value)); fs.Close(); } label1.Text ="更新完成"; File.Delete(Application.StartupPath+@"update.xml"; label1.Text ="正在重新啟動應用程序..."; System.Diagnostics.Process.Start("CustomerApplication.exe"; Close(); Application.Exit(); }這個代碼也很容易懂,首先就是找到主進程,如果沒有關閉,則用Process.Kill()來關閉主程序。然后則 用一個XmlDocument來Load程序生成的update.xml文件。用xml文件里指定的路徑和文件名來生成指 定的文件,在這之前先前已經存在的文件刪除。更新完畢后,則重新啟動主應用程序。這樣更新就完成了。 需要自動更新的時候,客戶端軟件提交更新請求給固定的網址,然后網址返回最新版本的版本號。如果更 新的是主程序,那么就必須關閉主程序了。自動更新程序如果發現主程序需要更新,在下載了升級補丁之 后,就會要求關閉主程序。[WebMethod(Description="取得更新版本"] public string GetVer() {XmlDocumentdoc=newXmlDocument();doc.Load(Server.MapPath("update.xml");XmlElementroot = doc.DocumentElement; return root.SelectSingleNode("version".InnerText; } 3 、 WebServices的GetUpdateData方法。 '轉載請注明出自外掛海官方論壇,本貼地址:http://bbs.wghai.com/thread-4747-1-1.html
轉載于:https://www.cnblogs.com/u0mo5/p/3973689.html
總結
- 上一篇: 设计模式 之 工厂模式
- 下一篇: github(5):GitHub的注册与