1、自动更新程序主要负责从服务器中获取相应的更新文件,并且把这些文件下载到本地,替换现有的文件。达到修复Bug,更新功能的目的。用户手工点击更新按钮启动更新程序。已测试。
2、环境VS2008,采用C#.NET和ASP.NET实现。
3、服务器:提供下载文件,发布出去。 文件包括:dll, xml,aspx等格式文件。其中update.xml 是记录更新文件的。
4、客户端:项目里面添加一个autoupdate.xml 文件,该文件里有连接服务器的发布更新文件的服务器地址。当客户端里userupdate.xml文件里的版本号和服务器中update.xml里的版本号对比,如果服务器的版本号高,提醒客户端更新。
5、源代码如下所示。
1)、服务端发布至IIS如下图所示。
图1
其中bin目录下的dll文件属性写入打勾。
图2
Update.xml源码如下所示。
代码
<
update
>
< version > 1.0.1.9 version >
< datetime > 2009-12-14 datetime >
< filelist filescount ="5" itemcount ="11" sourcepath ="http://Localhost/UpdateServ/" >
< file filesname ="" >
< item name ="xiaxia.txt" size ="" >
item >
file >
< file filesname ="UpFile" >
< item name ="2222.dll" size ="" >
item >
< item name ="1162193918505.doc" size ="" >
item >
< item name ="xd.doc" size ="" >
item >
< item name ="s2.txt" size ="" >
item >
< item name ="a.dll" size ="" >
item >
< item name ="WebUPFILE.dll" size ="" >
item >
file >
< file filesname ="test" >
< item name ="aa.txt" size ="" >
item >
< item name ="2.txt" size ="" >
item >
file >
< file filesname ="Copy" >
< item name ="bb.doc" size ="" >
item >
< item name ="b.dll" size ="" >
item >
file >
< file filesname ="hehe" >
< item name ="hehe.txt" size ="" >
item >
< item name ="WebUPFILE.dll" size ="" >
item >
file >
filelist >
update >
< version > 1.0.1.9 version >
< datetime > 2009-12-14 datetime >
< filelist filescount ="5" itemcount ="11" sourcepath ="http://Localhost/UpdateServ/" >
< file filesname ="" >
< item name ="xiaxia.txt" size ="" >
item >
file >
< file filesname ="UpFile" >
< item name ="2222.dll" size ="" >
item >
< item name ="1162193918505.doc" size ="" >
item >
< item name ="xd.doc" size ="" >
item >
< item name ="s2.txt" size ="" >
item >
< item name ="a.dll" size ="" >
item >
< item name ="WebUPFILE.dll" size ="" >
item >
file >
< file filesname ="test" >
< item name ="aa.txt" size ="" >
item >
< item name ="2.txt" size ="" >
item >
file >
< file filesname ="Copy" >
< item name ="bb.doc" size ="" >
item >
< item name ="b.dll" size ="" >
item >
file >
< file filesname ="hehe" >
< item name ="hehe.txt" size ="" >
item >
< item name ="WebUPFILE.dll" size ="" >
item >
file >
filelist >
update >
2)、客户端代码,结构如下图所示。
图3
代码内有注释,在此不再多说。
Config.cs
代码
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
namespace WebUpdate
{
public class Config
{
public string url = null ;
public string cmd = null ;
// 读文件autoUpdate.xml
public Config()
{
string path = AppDomain.CurrentDomain.BaseDirectory + " autoUpdate.xml " ;
try
{
if (path != null )
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(path);
url = xmlDoc.SelectSingleNode( " /update/url " ).InnerText;
}
}
catch (Exception ex)
{
throw new Exception( " 找不到autoUpdate.xml文件 " + ex.Message);
}
}
// 获取服务器的版本
public Version GetServerVersion()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(url);
return new Version(xmlDoc.SelectSingleNode( " /update/version " ).InnerText);
}
// 获取客户端版本
public string GetClientVersion()
{
url = AppDomain.CurrentDomain.BaseDirectory + " userVersion.xml " ;
XmlDocument xmlUser = new XmlDataDocument();
xmlUser.Load(url);
XmlElement root = xmlUser.DocumentElement;
XmlNode updateNode = root.SelectSingleNode( " version " );
string version = updateNode.Attributes[ " value " ].Value;
return version;
}
// 为了进行版本比较,进行转换为整数比较
public int ConvertVersion( string value)
{
int w, z, x, y, temp;
w = int .Parse(value.Substring( 0 , 1 ));
z = int .Parse(value.Substring( 2 , 1 ));
x = int .Parse(value.Substring( 4 , 1 ));
y = int .Parse(value.Substring( 6 , 1 ));
temp = w * 1000 + z * 100 + x * 10 + y;
return temp;
}
// 更新客户版本号为服务器的版本号
public string UpdateVersion( string serVersion)
{
url = AppDomain.CurrentDomain.BaseDirectory + " userVersion.xml " ;
XmlDocument xmlUser = new XmlDataDocument();
xmlUser.Load(url);
XmlElement root = xmlUser.DocumentElement;
XmlNode updateNode = root.SelectSingleNode( " version " );
string strVer = updateNode.Attributes[ " value " ].Value;
updateNode.Attributes[ " value " ].Value = serVersion;
xmlUser.Save(url);
return serVersion;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
namespace WebUpdate
{
public class Config
{
public string url = null ;
public string cmd = null ;
// 读文件autoUpdate.xml
public Config()
{
string path = AppDomain.CurrentDomain.BaseDirectory + " autoUpdate.xml " ;
try
{
if (path != null )
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(path);
url = xmlDoc.SelectSingleNode( " /update/url " ).InnerText;
}
}
catch (Exception ex)
{
throw new Exception( " 找不到autoUpdate.xml文件 " + ex.Message);
}
}
// 获取服务器的版本
public Version GetServerVersion()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(url);
return new Version(xmlDoc.SelectSingleNode( " /update/version " ).InnerText);
}
// 获取客户端版本
public string GetClientVersion()
{
url = AppDomain.CurrentDomain.BaseDirectory + " userVersion.xml " ;
XmlDocument xmlUser = new XmlDataDocument();
xmlUser.Load(url);
XmlElement root = xmlUser.DocumentElement;
XmlNode updateNode = root.SelectSingleNode( " version " );
string version = updateNode.Attributes[ " value " ].Value;
return version;
}
// 为了进行版本比较,进行转换为整数比较
public int ConvertVersion( string value)
{
int w, z, x, y, temp;
w = int .Parse(value.Substring( 0 , 1 ));
z = int .Parse(value.Substring( 2 , 1 ));
x = int .Parse(value.Substring( 4 , 1 ));
y = int .Parse(value.Substring( 6 , 1 ));
temp = w * 1000 + z * 100 + x * 10 + y;
return temp;
}
// 更新客户版本号为服务器的版本号
public string UpdateVersion( string serVersion)
{
url = AppDomain.CurrentDomain.BaseDirectory + " userVersion.xml " ;
XmlDocument xmlUser = new XmlDataDocument();
xmlUser.Load(url);
XmlElement root = xmlUser.DocumentElement;
XmlNode updateNode = root.SelectSingleNode( " version " );
string strVer = updateNode.Attributes[ " value " ].Value;
updateNode.Attributes[ " value " ].Value = serVersion;
xmlUser.Save(url);
return serVersion;
}
}
}
DownFile.cs
代码
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
namespace WebUpdate
{
public class DownFile
{
// 从服务器下载文件,若目录存在,直接复制新文件,不存在则新建目录并复制文件,成功后返回1
public bool DownFileFromServ( string url, string fileName)
{
bool downsucess = false ;
try
{
string fileExtraName = url.Split( char .Parse( " . " ))[ 0 ]; // 文件名
string fileAfterName = System.IO.Path.GetExtension(url); // 文件的扩展名
if (fileAfterName == " .aspx " )
url = fileAfterName + " .txt " ;
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
myReq.KeepAlive = true ;
HttpWebResponse myRes = (HttpWebResponse)myReq.GetResponse();
downsucess = this .CopyFileAndDirectory(myRes, fileName);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return downsucess;
}
// 返回复制文件或创建目录是否成功
public bool CopyFileAndDirectory(WebResponse myResp, string fileName)
{
bool flag = true ;
byte [] buffer = new byte [ 0x400 ];
try
{
int num;
// 若本身已有该目录则删除
if (System.IO.File.Exists(fileName))
{
System.IO.File.Delete(fileName);
}
// 创建目录更新到Updat目录下
string directoryName = Path.GetDirectoryName(fileName);
if ( ! Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
// 指定文件fileName不存在时创建它
Stream streamRead = System.IO.File.Open(fileName, FileMode.Create);
Stream responseStream = myResp.GetResponseStream();
do
{
// 从当前读取的字节流数,复制
num = responseStream.Read(buffer, 0 , buffer.Length);
if (num > 0 )
{
streamRead.Write(buffer, 0 , num);
}
}
while (num > 0 );
streamRead.Close();
responseStream.Close();
}
catch
{
flag = false ;
}
return flag;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
namespace WebUpdate
{
public class DownFile
{
// 从服务器下载文件,若目录存在,直接复制新文件,不存在则新建目录并复制文件,成功后返回1
public bool DownFileFromServ( string url, string fileName)
{
bool downsucess = false ;
try
{
string fileExtraName = url.Split( char .Parse( " . " ))[ 0 ]; // 文件名
string fileAfterName = System.IO.Path.GetExtension(url); // 文件的扩展名
if (fileAfterName == " .aspx " )
url = fileAfterName + " .txt " ;
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
myReq.KeepAlive = true ;
HttpWebResponse myRes = (HttpWebResponse)myReq.GetResponse();
downsucess = this .CopyFileAndDirectory(myRes, fileName);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return downsucess;
}
// 返回复制文件或创建目录是否成功
public bool CopyFileAndDirectory(WebResponse myResp, string fileName)
{
bool flag = true ;
byte [] buffer = new byte [ 0x400 ];
try
{
int num;
// 若本身已有该目录则删除
if (System.IO.File.Exists(fileName))
{
System.IO.File.Delete(fileName);
}
// 创建目录更新到Updat目录下
string directoryName = Path.GetDirectoryName(fileName);
if ( ! Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
// 指定文件fileName不存在时创建它
Stream streamRead = System.IO.File.Open(fileName, FileMode.Create);
Stream responseStream = myResp.GetResponseStream();
do
{
// 从当前读取的字节流数,复制
num = responseStream.Read(buffer, 0 , buffer.Length);
if (num > 0 )
{
streamRead.Write(buffer, 0 , num);
}
}
while (num > 0 );
streamRead.Close();
responseStream.Close();
}
catch
{
flag = false ;
}
return flag;
}
}
}
Update.cs
代码
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace WebUpdate
{
public class Update
{
// 从服务器文件update.xml中获取要下载的文件列表
public bool flag = false ;
public string [] GetFileList( string url)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(url);
XmlElement root = xmlDoc.DocumentElement;
XmlNode updateNode = root.SelectSingleNode( " filelist " );
string soucePath = updateNode.Attributes[ " sourcepath " ].Value;
string fileName = null ;
string fileList = null ;
// 取出服务器里update.xml里更新的file文件
XmlNodeList fileNode = updateNode.SelectNodes( " file " );
if (fileNode != null )
{
foreach (XmlNode i in fileNode)
{
foreach (XmlNode j in i)
{
if (i.Attributes[ " filesname " ].Value != "" )
fileName = soucePath + i.Attributes[ " filesname " ].Value + " / " + j.Attributes[ " name " ].Value +
" $ " + i.Attributes[ " filesname " ].Value + " / " + j.Attributes[ " name " ].Value;
else
fileName = soucePath + j.Attributes[ " name " ].Value +
" $ " + j.Attributes[ " name " ].Value;
fileName += " , " ;
fileList += fileName;
}
}
string [] splitFile = fileList.Split( ' , ' );
flag = true ;
return splitFile;
}
return null ;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace WebUpdate
{
public class Update
{
// 从服务器文件update.xml中获取要下载的文件列表
public bool flag = false ;
public string [] GetFileList( string url)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(url);
XmlElement root = xmlDoc.DocumentElement;
XmlNode updateNode = root.SelectSingleNode( " filelist " );
string soucePath = updateNode.Attributes[ " sourcepath " ].Value;
string fileName = null ;
string fileList = null ;
// 取出服务器里update.xml里更新的file文件
XmlNodeList fileNode = updateNode.SelectNodes( " file " );
if (fileNode != null )
{
foreach (XmlNode i in fileNode)
{
foreach (XmlNode j in i)
{
if (i.Attributes[ " filesname " ].Value != "" )
fileName = soucePath + i.Attributes[ " filesname " ].Value + " / " + j.Attributes[ " name " ].Value +
" $ " + i.Attributes[ " filesname " ].Value + " / " + j.Attributes[ " name " ].Value;
else
fileName = soucePath + j.Attributes[ " name " ].Value +
" $ " + j.Attributes[ " name " ].Value;
fileName += " , " ;
fileList += fileName;
}
}
string [] splitFile = fileList.Split( ' , ' );
flag = true ;
return splitFile;
}
return null ;
}
}
}
autoUpdate.xml
<
update
>
< url > http://Localhost/UpdateServ/update.xml url >
update >
< url > http://Localhost/UpdateServ/update.xml url >
update >
userVersion.xml
xml version="1.0" encoding="utf-8"
?>
< update >
< version value ="1.0.1.9" > 客户端版本号 version >
update >
< update >
< version value ="1.0.1.9" > 客户端版本号 version >
update >
Update.aspx
代码
<%
@ Page Language
=
"
C#
"
AutoEventWireup
=
"
true
"
CodeFile
=
"
Update.aspx.cs
"
Inherits
=
"
_Default
"
%>
DOCTYPE html PUBLIC " -//W3C//DTD XHTML 1.0 Transitional//EN " " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd " >
< html xmlns = " http://www.w3.org/1999/xhtml " >
< head runat = " server " >
< title > 自动更新 title >
head >
< body >
< form id = " form1 " runat = " server " >
< div >
< br />
< br />
< asp:Label ID = " lblDisplay " runat = " server " style = " text-align: center " mce_style = " text-align: center "
Text = " Label " Visible = " False " > asp:Label >
< br />
< br />
< asp:Button ID = " btnUpdate " runat = " server " style = " text-align: center " mce_style = " text-align: center "
Text = " 更新 " onclick = " btnUpdate_Click " Visible = " False " Height = " 34px "
Width = " 145px " />
< br />
< br />
< asp:Label ID = " NewVersion " runat = " server " Text = " Label1 " Visible = " false " > asp:Label >
< br />
< br />
< asp:Label ID = " CurrentVersion " runat = " server " Text = " Label2 " Visible = " false " > asp:Label >
div >
form >
body >
html >
DOCTYPE html PUBLIC " -//W3C//DTD XHTML 1.0 Transitional//EN " " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd " >
< html xmlns = " http://www.w3.org/1999/xhtml " >
< head runat = " server " >
< title > 自动更新 title >
head >
< body >
< form id = " form1 " runat = " server " >
< div >
< br />
< br />
< asp:Label ID = " lblDisplay " runat = " server " style = " text-align: center " mce_style = " text-align: center "
Text = " Label " Visible = " False " > asp:Label >
< br />
< br />
< asp:Button ID = " btnUpdate " runat = " server " style = " text-align: center " mce_style = " text-align: center "
Text = " 更新 " onclick = " btnUpdate_Click " Visible = " False " Height = " 34px "
Width = " 145px " />
< br />
< br />
< asp:Label ID = " NewVersion " runat = " server " Text = " Label1 " Visible = " false " > asp:Label >
< br />
< br />
< asp:Label ID = " CurrentVersion " runat = " server " Text = " Label2 " Visible = " false " > asp:Label >
div >
form >
body >
html >
Update.aspx.cs
代码
using
System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using WebUpdate;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{
lblDisplay.Text = "" ;
btnUpdate.Visible = false ;
Config cf = new Config();
NewVersion.Text = cf.GetServerVersion().ToString();
CurrentVersion.Text = cf.GetClientVersion().ToString();
int clientversion = cf.ConvertVersion(CurrentVersion.Text);
int serverversion = cf.ConvertVersion(NewVersion.Text);
if (serverversion > clientversion)
{
btnUpdate.Visible = true ;
}
else
{
lblDisplay.Text = " 已是最新版本,不需要更新! " ;
lblDisplay.Visible = true ;
}
}
protected void btnUpdate_Click( object sender, EventArgs e)
{
string url = null ;
string [] files = null ;
Config updatecf = new Config();
url = updatecf.url;
Update upd = new Update();
files = upd.GetFileList(url);
UpdateFile(files);
CurrentVersion.Text = updatecf.UpdateVersion(NewVersion.Text);
lblDisplay.Text = " 更新完成。 " ;
lblDisplay.Visible = true ;
btnUpdate.Visible = false ;
}
private void UpdateFile( string [] files)
{
if ((files == null ) || (files.Length <= 0 ))
{
Response.Write( " 升级完成 " );
}
else
{
int num = 0 ;
for ( int i = 0 ; i < files.Length; i ++ )
{
string str = files[i];
if ((str != null ) && (str.Split( new char [] { ' $ ' }).Length == 2 ))
{
string [] strArray = str.Split( new char [] { ' $ ' });
this .UpdateFile(strArray[ 0 ], strArray[ 1 ]);
num ++ ;
}
}
if (num == 0 )
{
Response.Write( " 升级完成 " );
}
}
}
private void UpdateFile( string url, string filename)
{
string fileName = AppDomain.CurrentDomain.BaseDirectory + filename;
try
{
DownFile file = new DownFile();
bool flag = file.DownFileFromServ(url, fileName);
}
catch
{
}
}
}
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using WebUpdate;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{
lblDisplay.Text = "" ;
btnUpdate.Visible = false ;
Config cf = new Config();
NewVersion.Text = cf.GetServerVersion().ToString();
CurrentVersion.Text = cf.GetClientVersion().ToString();
int clientversion = cf.ConvertVersion(CurrentVersion.Text);
int serverversion = cf.ConvertVersion(NewVersion.Text);
if (serverversion > clientversion)
{
btnUpdate.Visible = true ;
}
else
{
lblDisplay.Text = " 已是最新版本,不需要更新! " ;
lblDisplay.Visible = true ;
}
}
protected void btnUpdate_Click( object sender, EventArgs e)
{
string url = null ;
string [] files = null ;
Config updatecf = new Config();
url = updatecf.url;
Update upd = new Update();
files = upd.GetFileList(url);
UpdateFile(files);
CurrentVersion.Text = updatecf.UpdateVersion(NewVersion.Text);
lblDisplay.Text = " 更新完成。 " ;
lblDisplay.Visible = true ;
btnUpdate.Visible = false ;
}
private void UpdateFile( string [] files)
{
if ((files == null ) || (files.Length <= 0 ))
{
Response.Write( " 升级完成 " );
}
else
{
int num = 0 ;
for ( int i = 0 ; i < files.Length; i ++ )
{
string str = files[i];
if ((str != null ) && (str.Split( new char [] { ' $ ' }).Length == 2 ))
{
string [] strArray = str.Split( new char [] { ' $ ' });
this .UpdateFile(strArray[ 0 ], strArray[ 1 ]);
num ++ ;
}
}
if (num == 0 )
{
Response.Write( " 升级完成 " );
}
}
}
private void UpdateFile( string url, string filename)
{
string fileName = AppDomain.CurrentDomain.BaseDirectory + filename;
try
{
DownFile file = new DownFile();
bool flag = file.DownFileFromServ(url, fileName);
}
catch
{
}
}
}