利用webservice实现软件自动更新(auto update)
winform程序相对web程序而言,功能更强大,编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题,在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术方案,弥补了这一缺陷,有较好的参考价值。 一、升级的好处。 长期以来,广大程序员为到底是使用Client/Server,还是使用Browser/Server结构争论不休,在这些争论当中,C/S结构的程序的可维护性差,布置困难,升级不方便,维护成本高就是一个相当重要的因素,也是那些B/S的支持者们将Client/Server结构打入地狱的一个重要原因。 现在好了,我们就在最新的基于Microsoft 的 WinForm上用WebServices来实现软件的自动升级功能。二、升级的技术原理。 升级的原理有好几个,首先无非是将现有版本与最新版本作比较,发现最新的则提示用户是否升级。当然也有人用其它属性比较的,例如:文件大小。:) 或者更新日期。 三、在.Net时代的实现。 在.Net时代,我们就有了更多的选择,可以使用WebRequest,也可以使用WebServices。在这里我们将用WebServices来实现软件的自动升级。 实现原理:在WebServices中实现一个GetVer的WebMethod方法,其作用是获取当前的最新版本。 然后将现在版本与最新版本比较,如果有新版本,则进行升级。 步骤: 1、准备一个XML文件 (Update.xml)。 view plaincopy to clipboardprint?<?xml version="1.0" encoding="utf-8" ?>??? <product>??? <version>1.0.1818.42821</version>??? <description>修正一些Bug</description>??? <filelist count="4" sourcepath="./update/">??? <item name="City.xml" size="">??? <value />??? </item>??? <item name="CustomerApplication.exe" size="">??? <value />??? </item>??? <item name="Interop.SHDocVw.dll" size="">??? <value />??? </item>??? <item name="Citys.xml" size="">??? <value />??? </item>??? </filelist>??? </product>?? <?xml version="1.0" encoding="utf-8" ?> <product> <version>1.0.1818.42821</version> <description>修正一些Bug</description> <filelist count="4" sourcepath="./update/"> <item name="City.xml" size=""> <value /> </item> <item name="CustomerApplication.exe" size=""> <value /> </item> <item name="Interop.SHDocVw.dll" size=""> <value /> </item> <item name="Citys.xml" size=""> <value /> </item> </filelist> </product>? 作用是作为一个升级用的模板。 2、WebServices的GetVer方法。 ????????? view plaincopy to clipboardprint?[WebMethod(Description="取得更新版本")]?? ????????? public string GetVer()?? ????????? {?? ??????????????? XmlDocument doc = new XmlDocument();?? ??????????????? doc.Load(Server.MapPath("update.xml"));?? ??????????????? XmlElement root = doc.DocumentElement;?? ??????????????? return root.SelectSingleNode("version").InnerText;?? ????????? }? ? [WebMethod(Description="取得更新版本")]??????????? public string GetVer()??????????? {????????????????? XmlDocument doc = new XmlDocument();????????????????? doc.Load(Server.MapPath("update.xml"));????????????????? XmlElement root = doc.DocumentElement;????????????????? return root.SelectSingleNode("version").InnerText;??????????? } 3、WebServices的GetUpdateData方法。 ?????????? view plaincopy to clipboardprint?[WebMethod(Description="在线更新软件")]?? ?????????? [SoapHeader("sHeader")]?? ?????????? public System.Xml.XmlDocument GetUpdateData()?? ?????????? {?? ???????????????? //验证用户是否登陆?? ???????????????? if(sHeader==null)?? ?????????????????????? return null;?? ???????????????? if(!DataProvider.GetInstance.CheckLogin(sHeader.Username,sHeader.Password))?? ?????????????????????? return null;?? ???????????????? //取得更新的xml模板内容?? ???????????????? XmlDocument doc = new XmlDocument();?? ???????????????? doc.Load(Server.MapPath("update.xml"));?? ???????????????? XmlElement root = doc.DocumentElement;?? ???????????????? //看看有几个文件需要更新?? ???????????????? XmlNode updateNode = root.SelectSingleNode("filelist");?? ???????????????? string path = updateNode.Attributes["sourcepath"].Value;?? ???????????????? int count = int.Parse(updateNode.Attributes["count"].Value);?? ???????????????? //将xml中的value用实际内容替换?? ???????????????? for(int i=0;i<count;i++)?? ???????????????? {?? ?????????????????????? XmlNode itemNode = updateNode.ChildNodes[i];?? ?????????????????????? string fileName = path + itemNode.Attributes["name"].Value;?? ?????????????????????? FileStream fs = File.OpenRead(Server.MapPath(fileName));?? ?????????????????????? itemNode.Attributes["size"].Value = fs.Length.ToString();?? ?????????????????????? BinaryReader br = new BinaryReader(fs);?? ?????????????????????? //这里是文件的实际内容,使用了Base64String编码?? ?????????????????????? itemNode.SelectSingleNode("value").InnerText =??? onvert.ToBase64String(br.ReadBytes((int)fs.Length),(int)fs.Length);?? ?????????????????????? br.Close();?? ?????????????????????? fs.Close();?? ???????????????? }?? ???????????????? return doc;?? ?????????? }? ?[WebMethod(Description="在线更新软件")]??????????? [SoapHeader("sHeader")]??????????? public System.Xml.XmlDocument GetUpdateData()??????????? {????????????????? //验证用户是否登陆????????????????? if(sHeader==null)??????????????????????? return null;????????????????? if(!DataProvider.GetInstance.CheckLogin(sHeader.Username,sHeader.Password))??????????????????????? return null;????????????????? //取得更新的xml模板内容????????????????? XmlDocument doc = new XmlDocument();????????????????? doc.Load(Server.MapPath("update.xml"));????????????????? XmlElement root = doc.DocumentElement;????????????????? //看看有几个文件需要更新????????????????? XmlNode updateNode = root.SelectSingleNode("filelist");????????????????? string path = updateNode.Attributes["sourcepath"].Value;????????????????? int count = int.Parse(updateNode.Attributes["count"].Value);????????????????? //将xml中的value用实际内容替换????????????????? for(int i=0;i<count;i++)????????????????? {??????????????????????? XmlNode itemNode = updateNode.ChildNodes[i];??????????????????????? string fileName = path + itemNode.Attributes["name"].Value;??????????????????????? FileStream fs = File.OpenRead(Server.MapPath(fileName));??????????????????????? itemNode.Attributes["size"].Value = fs.Length.ToString();??????????????????????? BinaryReader br = new BinaryReader(fs);??????????????????????? //这里是文件的实际内容,使用了Base64String编码??????????????????????? itemNode.SelectSingleNode("value").InnerText = Convert.ToBase64String(br.ReadBytes((int)fs.Length),(int)fs.Length);??????????????????????? br.Close();??????????????????????? fs.Close();????????????????? }????????????????? return doc;??????????? } 4、在客户端进行的工作。 首先引用此WebServices,例如命名为:WebSvs, view plaincopy to clipboardprint?string nVer = Start.GetService.GetVer(); ?? if(Application.ProductVersion.CompareTo(nVer)<=0)??? update();?? string nVer = Start.GetService.GetVer(); if(Application.ProductVersion.CompareTo(nVer)<=0) update();? ? 在本代码中 Start.GetService是WebSvs的一个Static 实例。首先检查版本,将结果与当前版本进行比较,如果为新版本则执行UpDate方法。????????? view plaincopy to clipboardprint?void update()?? ????????? {?? ??????????????? this.statusBarPanel1.Text = "正在下载...";?? ??????????????? System.Xml.XmlDocument doc = ((System.Xml.XmlDocument)Start.GetService.GetUpdateData());?? ??????????????? doc.Save(Application.StartupPath + @"/update.xml");?? ??????????????? System.Diagnostics.Process.Start(Application.StartupPath + @"/update.exe");?? ??????????????? Close();?? ??????????????? Application.Exit();?? ????????? }? ? void update()??????????? {????????????????? this.statusBarPanel1.Text = "正在下载...";????????????????? System.Xml.XmlDocument doc = ((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 的内容。?????????? view plaincopy to clipboardprint?private void Form1_Load(object sender,System.EventArgs e)?? ????????? {?? ??????????????? System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcesses();?? ??????????????? foreach(System.Diagnostics.Process p in ps)?? ??????????????? {?? ????????????????????? //MessageBox.Show(p.ProcessName);?? ????????????????????? if(p.ProcessName.ToLower()=="customerapplication")?? ????????????????????? {?? ??????????????????????????? p.Kill();?? ??????????????????????????? break;?? ????????????????????? }?? ??????????????? }?? ??????????????? XmlDocument doc = new XmlDocument();?? ??????????????? doc.Load(Application.StartupPath + @"/update.xml");?? ??????????????? XmlElement root = doc.DocumentElement;?? ??????????????? XmlNode updateNode = root.SelectSingleNode("filelist");?? ??????????????? string path = updateNode.Attributes["sourcepath"].Value;?? ??????????????? int count = int.Parse(updateNode.Attributes["count"].Value);?? ??????????????? for(int i=0;i<count;i++)?? ??????????????? {?? ????????????????????? XmlNode itemNode = updateNode.ChildNodes[i];?? ????????????????????? string fileName = itemNode.Attributes["name"].Value;?? ????????????????????? FileInfo fi = new FileInfo(fileName);?? ????????????????????? fi.Delete();?? ????????????????????? //File.Delete(Application.StartupPath + @"/" + fileName);?? ????????????????????? this.label1.Text = "正在更新: " + fileName + " (" + itemNode.Attributes["size"].Value + ") ...";?? ????????????????????? FileStream fs = File.Open(fileName,FileMode.Create,FileAccess.Write);?? ????????????????????? fs.Write(System.Convert.FromBase64String(itemNode.SelectSingleNode("value").InnerText),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();?? ????????? }? ? private void Form1_Load(object sender,System.EventArgs e)??????????? {????????????????? System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcesses();????????????????? foreach(System.Diagnostics.Process p in ps)????????????????? {??????????????????????? //MessageBox.Show(p.ProcessName);??????????????????????? if(p.ProcessName.ToLower()=="customerapplication")??????????????????????? {????????????????????????????? p.Kill();????????????????????????????? break;??????????????????????? }????????????????? }????????????????? XmlDocument doc = new XmlDocument();????????????????? doc.Load(Application.StartupPath + @"/update.xml");????????????????? XmlElement root = doc.DocumentElement;????????????????? XmlNode updateNode = root.SelectSingleNode("filelist");????????????????? string path = updateNode.Attributes["sourcepath"].Value;????????????????? int count = int.Parse(updateNode.Attributes["count"].Value);????????????????? for(int i=0;i<count;i++)????????????????? {??????????????????????? XmlNode itemNode = updateNode.ChildNodes[i];??????????????????????? string fileName = itemNode.Attributes["name"].Value;??????????????????????? FileInfo fi = new FileInfo(fileName);??????????????????????? fi.Delete();??????????????????????? //File.Delete(Application.StartupPath + @"/" + fileName);??????????????????????? this.label1.Text = "正在更新: " + fileName + " (" + itemNode.Attributes["size"].Value + ") ...";??????????????????????? FileStream fs = File.Open(fileName,FileAccess.Write);??????????????????????? fs.Write(System.Convert.FromBase64String(itemNode.SelectSingleNode("value").InnerText),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文件里指定的路径和文件名来生成指定 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |