C# WinForm实现自动更新程序之客户端的完整攻略
前言
随着软件的不断版本升级,客户端自动更新已成为开发者和用户比较看重的一个功能。本文将从客户端实现的角度讲解C# WinForm应用程序的自动更新。
实现思路
客户端自动更新的实现基本思路为:
- 从服务端获取最新版本信息
- 如果本地版本与最新版本不一致,下载更新包并进行更新
其中,获取最新版本信息的方式通常有两种:一种是通过HTTP请求服务端接口获得最新版本号及更新包下载地址等数据,另一种是通过FTP发布服务器上传更新包,并在客户端程序中手动指定发布服务器地址和路径获得更新包。
实现客户端自动更新,我们需要完成以下任务:
- 在服务器端,生成版本信息配置文件和更新包
- 在客户端,下载版本信息配置文件,判断是否需要更新,下载更新包,替换本地文件
服务器端配置
生成更新包
生成更新包需要用到一个第三方软件:AdvancedInstaller。我们可以使用AdvancedInstaller帮助我们生成更新包。
首先,我们需要在AdvancedInstaller中创建我们的项目,将我们需要打包的文件添加进去,包括安装文件(.msi文件)、配置文件等。
若需要添加新的文件则按步骤进行——
1. 在Project中找到Files and Folders->Files,点击add,选择你需要添加的文件,放入项目中
2. 将其放在你需要的文件夹下,保证在同一个目录下自己下载的程序同上次正常使用的程序资源相同
3. 最后打开你的安装文件设置Custom Actions。在Uninstall 和 Install 前需要分别添加 Delete Folder 和 Copy Folder 的操作。具体操作和实例讲解可以在advancedinstaller官网中找到。
完成后,使用AdvancedInstaller创建一个更新包。打开AdvancedInstaller,选择“Tools”->“Media Builder”,在Media Type中选择“Patch”,然后按照提示添加需要更新的目标版本和更新包(.aip)即可生成更新包(.msp)。
生成版本信息配置文件
更新包生成后,我们还需要生成对应的版本信息配置文件。这个配置文件用于存储最新版本号及更新包下载地址等信息。
一般情况下我们使用XML文件作为配置文件。配置文件中需要记录最新版本号、更新日志和更新包文件名等信息,其格式大致如下:
<?xml version="1.0" encoding="utf-8"?>
<UpdateInfo>
<Version>1.2.0.0</Version>
<UpdateLog>这是1.2.0.0版本的更新日志</UpdateLog>
<Url>http://download.site.com/APP/Update/1.2.0.0.zip</Url>
</UpdateInfo>
其中,Version节点为最新版本号,UpdateLog节点为更新日志,Url节点为更新包下载地址。
客户端实现
在客户端实现自动更新可以使用HttpWebRequest,这个类就是负责Http封装的类,方便我们发送http请求。既可以发送post请求,也可以发送get请求,他的具体使用方法和原理可以自行百度或者查阅官网。本次仅给出具体代码和一个简单的说明。注意:由于国内网络因素,示例代码中的请求地址需要自行替换为合适的下载地址,并且示例代码中未进行错误处理,生产环境中需要增加连接超时和异常处理等功能。
下载更新包
客户端要实现自动更新,需要将从服务器获取到的版本信息配置文件下载到本地。我们可以使用HttpWebRequest类向服务器发送Http请求,并使用StreamReader类读取服务器返回的XML文件内容。一般情况下我们使用XML文件作为配置文件。配置文件中需要记录最新版本号、更新日志和更新包文件名等信息,其格式大致如下:
// 下载配置文件
public static string HttpDownload(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
using (Stream stream = request.GetResponse().GetResponseStream())
{
using (StreamReader sr = new StreamReader(stream))
{
return sr.ReadToEnd();
}
}
}
下载更新包的方法也很简单,直接使用WebClient类实现。以下是一个简单的下载更新包的示例代码:
// 下载更新包
public static void DownloadFile(string url, string file)
{
WebClient webClient = new WebClient();
// 防止服务器上的文件名和本地不同名,所以用了也强制覆盖
webClient.DownloadFile(url, file);
webClient.Dispose();
}
更新本地应用程序
下载到新版后,客户端需要更新本地应用程序。具体做法如下:
// 更新本地应用程序
private static void UpdateFiles(string localFolder, string remoteFolder)
{
DirectoryInfo di = new DirectoryInfo(localFolder);
FileInfo[] localFiles = di.GetFiles("*.*", SearchOption.AllDirectories);
string updateFolder = Path.Combine(localFolder, "_UpdateTemp");
Directory.CreateDirectory(updateFolder);
// 下载更新文件
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(Path.Combine(remoteFolder, "UpdateInfo.xml"));
XmlNode node = xmldoc.SelectSingleNode("UpdateInfo/Version");
string updateVersion = node.InnerText;
XmlNode nodeFile = xmldoc.SelectSingleNode("UpdateInfo/Url");
string serverPath = nodeFile.InnerText;
string updateFileName = serverPath.Substring(serverPath.LastIndexOf("/") + 1);
if (!Directory.Exists(updateFolder)) Directory.CreateDirectory(updateFolder);
DownloadFile(serverPath, Path.Combine(updateFolder, updateFileName));
// 更新本地文件
foreach (FileInfo file in localFiles)
{
if (file.FullName.ToLower().Contains("updatetemp")) continue;
FileInfo newFile = new FileInfo(Path.Combine(updateFolder, file.Name));
if (newFile.Exists)
{
file.CopyTo(file.FullName + "_bak", true);
newFile.CopyTo(file.FullName, true);
newFile.Delete();
}
}
}
示例说明
以下是一个简单的示例,演示了如何实现“检测更新->下载更新->更新本地文件”的流程。
假设我们有一个WinForm程序,程序名为“Demo.exe”,当前版本号为1.0.0.0,在当前程序目录下有一个配置文件“UpdateInfo.xml”(用于存储最新版本号、更新日志、更新文件名等信息),并且程序采用HTTP对外提供更新服务。服务器地址为:http://download.site.com。
示例1:检测更新
以下代码演示了如何检测是否需要更新。
public bool CheckUpdate()
{
try
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(Path.Combine(Application.StartupPath, "UpdateInfo.xml"));
XmlNode node = xmldoc.SelectSingleNode("UpdateInfo/Version");
string currentVersion = node.InnerText;
string remoteUrl = "http://download.site.com/APP/UpdateInfo.xml";
xmldoc.LoadXml(HttpDownload(remoteUrl));
node = xmldoc.SelectSingleNode("UpdateInfo/Version");
string remoteVersion = node.InnerText;
if (remoteVersion != currentVersion)
{
_updateFolder = Path.Combine(Application.StartupPath, "_UpdateTemp");
if (!Directory.Exists(_updateFolder)) Directory.CreateDirectory(_updateFolder);
return true;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return false;
}
示例2:下载更新和更新本地文件
以下代码演示了如何下载更新包,以及如何更新本地文件。
public void DoUpdate()
{
try
{
string remoteFolder = "http://download.site.com/APP/";
string updateFile = "_UpdateTemp\\UpdateInfo.xml";
DownloadFile(remoteFolder + "UpdateInfo.xml", Path.Combine(Application.StartupPath, updateFile));
UpdateFiles(Application.StartupPath, remoteFolder);
Process.Start(Application.ExecutablePath);
Application.Exit(); // 如果不加这句话,无法释放被程序占用的dll文件
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
结语
本文从实现思路、服务器端配置和客户端实现等方面介绍了C# WinForm应用程序的自动更新。在实际开发中,开发者需要根据自己的实际情况对代码做出相应的调整。同时,在多个示例中演示的代码并未进行错误处理等操作,开发者需要根据自己的实际情况对代码进行优化。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# WinForm实现自动更新程序之客户端的示例代码 - Python技术站