惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
腾讯CDC
D
Docker
G
Google Developers Blog
D
DataBreaches.Net
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
S
SegmentFault 最新的问题
The Cloudflare Blog
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
量子位
美团技术团队
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - zhangh

[转]铁路订票网站个人的设计浅见 新写了一个Web即时通程序,基于HTTP长连接的服务器推技术。 .NET Framework 3.5 SP1安装时下载文件问题及精简方法2(转) [转] javascript基础知识大集锦(2) 迪士尼近期将拓展中国三线城市的市场 迪士尼礼品批发网 Web Service WSE 3.0 creation time in the timestamp cannot be in the future 局域网内机器访问服务器数据库连接,访问Web Service需要密码 - zhangh - 博客园 Web Service "Unsupported media type error" ubuntu下配置eclipse3.3 ubuntu下配置tomcat Ubuntu下配置samba实现文件夹共享 Open Source URL Rewriter for .NET / IIS / ASP.NET 要实现动态加载JS脚本有4种方法 - zhangh - 博客园 使用XML文件来动态配置ASP.NET MVC的Route规则 - zhangh - 博客园 window.opener - zhangh - 博客园 多线程断点续传研究之二 多线程断点续传研究之一 winform登录窗口的正确操作办法
在WinForm中使用Web Services 来实现 软件 自动升级( Auto Up...
zhangh · 2009-01-07 · via 博客园 - zhangh

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 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文件里指定的路径和文件名来生成指定的文件,在这之前先前已经存在的文件删除。更新完毕后,则重新启动主应用程序。这样更新就完成了。
四、总结:
  从这个实例看来,WebService的工作是很简单的,也是很容易实现的。好好的使用WebService能够为我们的程序带来很多新的,强的功能。总而言之,.Net是易用的,强大的语言。如果大家对本代码有任何意见,欢迎光临《开发者》论坛: http://forums.coder.cn/ ,希望和大家共同探讨。
此文亦发表在本人Blog上:http://blogs.coder.cn/skyover/archive/2004/06/07/485.aspx

新闻来自: 新客网(www.xker.com) 详文参考:http://www.xker.com/page/e2007/0116/12818.html