天天看點

軟體更新原理

自動更新的時候,用戶端軟體送出更新請求給固定的網址,然後網址傳回最新版本的版本号。用戶端 軟體和自己的版本号對比,如果發現伺服器的版本和自己的版本不一樣,那麼就請求下載下傳更新更新檔。服務 器響應請求,提供更新檔下載下傳;下載下傳成功後,手動或自動安裝一下就可以了。 安裝更新檔的時候,用戶端的主程式一般是要關閉的,除非采用動态解除安裝、調入元件的技術,比如網絡 遊戲,就是盡量讓玩家邊玩遊戲邊更新。 如果更新的是主程式,那麼就必須關閉主程式了。可是主程式關閉了之後,誰來調用安裝更新檔呢?為 了解決這個問題,人們把主程式和自動更新程式分開來做。當需要校驗版本的時候,主程式調用自動更新 程式。自動更新程式如果發現主程式需要更新,在下載下傳了更新更新檔之後,就會要求關閉主程式。主程式關 閉之後,自動更新程式調用更新更新檔進行安裝,安裝完成後再重新啟動主程式。自動更新程式自動退出, 完成更新任務。這和你剛才關閉電腦後再插網卡的原理是一模一樣的。其實生活中有很多現象可以借鑒到 軟體設計中。 人們嫌這樣的更新仍然太麻煩,後來出現了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