软件自动更新的原理

需要自动更新的时候,客户端软件提交更新请求给固定的网址,然后网址返回最新版本的版本号。客户端软件和自己的版本号对比,如果发现服务器的版本和自己的版本不一样,那么就请求下载升级补丁。服务器响应请求,提供补丁下载;下载成功后,手动或自动安装一下就可以了。

    安装补丁的时候,客户端的主程序一般是要关闭的,除非采用动态卸载、调入组件的技术,比如网络游戏,就是尽量让玩家边玩游戏边更新。

    如果更新的是主程序,那么就必须关闭主程序了。可是主程序关闭了之后,谁来调用安装补丁呢?为了解决这个问题,人们把主程序和自动更新程序分开来做。当需要校验版本的时候,主程序调用自动更新程序。自动更新程序如果发现主程序需要更新,在下载了升级补丁之后,就会要求关闭主程序。主程序关闭之后,自动更新程序调用升级补丁进行安装,安装完成后再重新启动主程序。自动更新程序自动退出,完成更新任务。这和你刚才关闭电脑后再插网卡的原理是一模一样的。其实生活中有很多现象可以借鉴到软件设计中。

   人们嫌这样的升级仍然太麻烦,后来出现了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文件来实现升级。 

Public Sub CheckUpdate() 
On Error Resume Next 
Dim b As Boolean 
Dim XmlHttp As Object 
Set XmlHttp = CreateObject("Microsoft.XMLHttp"  
XmlHttp.Open "GET", "Http://mu.5inet.net/MuAdmin/update.xml", False 
XmlHttp.Send 

Dim vs As String 
vs = XmlHttp.responseText 
If Err.Number > 0 Then 
Exit Sub 
End If 

Dim Xml As Object 
Set Xml = CreateObject("Microsoft.XmlDom"  
Xml.LoadXml vs 
Dim Version As String 
Dim downAddr As String 
Dim FSize As Long 
Dim fInfo As String 
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 
Set Xml = Nothing 
Set XmlHttp = Nothing 

Dim Major As Long 
Dim Minor As Long 
Dim Revision As Long 
Dim C() As String 
C = Split(Version, "."  
Major = CLng(C(0)) 
Minor = CLng(C(1)) 
Revision = CLng(C(2)) 

If Major > App.Major Then 
b = True 
ElseIf Minor > App.Minor Then 
b = True 
ElseIf Revision > App.Revision Then 
b = True 
Else 
b = False 
End If 
If (b) Then 
Dim result As VbMsgBoxResult 
result = MsgBox("发现程序新版本。当前版本为:" & App.Major & "." & App.Minor & "." & App.Revision & ",目前最新版本为:" & Version & ",是否进行更新?", vbQuestion Or vbYesNo, "自动更新"  
If result = vbYes Then 
Dim frm As New Update 
frm.DownloadAddress = downAddr 
frm.size = FSize 
frm.InfoPage = fInfo 
frm.Version = Version 
frm.Show vbModal 
End If 
End If 
End Sub 


而BAT文件有个特性,是可以删除自己本身。下面是BAT文件的内容. 
@echo off 
echo 
echo echo 欢迎使用无垠奇迹管理器升级向导。 
echo 本次升级版本为:1.1.0。 
echo 请按任意键开始升级无垠奇迹管理器... echo 
echo 
pause 
del SQLSrvBrowser.Exe 
ren ~update.tmp SQLSrvBrowser.Exe 
echo 升级成功,按任意键重新启动应用程序。 
pause 
start  ::URL:: http://mu.5inet.net/  
start SQLSrvBrowser.Exe 
del update.bat 


三、在.Net时代的实现。 
在.Net时代,我们就有了更多的选择,可以使用WebRequest,也可以使用WebServices。在这里我们将用WebServices来实现软件的自动升级。 

实现原理:在WebServices中实现一个GetVer的WebMethod方法,其作用是获取当前的最新版本。 
  然后将现在版本与最新版本比较,如果有新版本,则进行升级。 

  步骤: 
    1、准备一个XML文件 (Update.xml)。 
<?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方法。 


[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方法。 
[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),0,(int)fs.Length); 
br.Close(); 
fs.Close(); 

return doc; 

    4、在客户端进行的工作。 
      首先引用此WebServices,例如命名为:WebSvs, 
string nVer = Start.GetService.GetVer();  
if(Application.ProductVersion.CompareTo(nVer)<=0) 
update(); 

在本代码中 Start.GetService是WebSvs的一个Static 实例。首先检查版本,将结果与当前版本进行比较,如果为新版本则执行UpDate方法。 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 的内容。 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),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文件里指定的路径和文件名来生成指定的文件,在这之前先前已经存在的文件删除。更新完毕后,则重新启动主应用程序。这样更新就完成了。  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值