自动升级的原理及C#代码实现
原文地址,原文的格式更规范写
http://blog.csdn.net/xuexiaodong2009/article/details/6640323
C/S程序自动升级是一个很重要的功能,原理其实很简单,一般包含两个程序一个是主程序,也就是除了升级功能以外的程序,另一个就是升级程序,常见的360,金山安全卫士都是这样。
主要包括以下几点: 1 比较版本 2下载文件 3更新文件 4启动主程序。但其中的需要注意的细节很多。
一般服务端会有一个配置文件包含最新更新的文件信息的配置文件,当然这些更新信息也可以存到数据库,或者其他地方。客户端(也就是需要更新的那部分程序)也有一个配置文件包含客户端版本信息,这些信息可以存到专门的一个配置文件中,或者是config文件中,没有一定的规定,可以根据实际设计。
在客户端程序启动时,先启动更新程序通过比较本地版本和服务端最新的版本信息判断是否有新版本,如果有可以直接下载,下载完成替换成功后并更新客户端版本信息,启动主程序。
缺点:如果更新速度由于更新的文件很大或者网速很慢,用户不得不等待很长时间,直到下载完成或者下载失败。
优点:处理完成后,启动的直接就是更新后的程序。不会出现由于主程序在运行导致替换文件之类的错误。
另一种方法是, 在客户端段程序启动时,启动更新程序,但更新程序不做版本判断,到客户端更新目录下检查有没有下载的新版本,如果有就更新主程序并更新客户端版本信息,然后启动主程序,如果没有就直接启动主程序。由主程序判断是否有新版本,并在后台下载把文件放到客户端更新目录中,下载完成后,提示用户退出主程序,重新启动,在启动时由更新程序并更新客户端和客户端版本信息。
缺点:由于下载是在主程序的后台运行,可能会影响主程序的处理速度。
优点:避免了由于下载导致用户长时间的等待。
1 比较版本
比较依据:
可以通过文件的最后修改时间,或者使用文件版本作为比较依据,使用文件最后修改时间显然不是标准的做法,但也没有错误,但需要注意日期的格式一定要统一,避免日 期格式不一致导致错误。可以使用Fileinfo类获取最后修改时间。
FIleInfo类官网参考
http://forum.csdn.net/PointForum/Forum/PostTopic.aspx?forumID=e2798a59-79d5-4833-9c57-87d46a8b907a
使用文件版本作为标准,则每次修改时必须修改版本号,C#程序就是要修AssemblyInfo.cs文件中的内容了,多了一步,规范多了。Version类处理版本信息并比较。
Assembly thisAssem = Assembly.GetExecutingAssembly();
AssemblyName thisAssemName = thisAssem.GetName();
Version ver = thisAssemName.Version;
Uri uri = new Uri(downFileUrl + localFileName);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Credentials = CredentialCache.DefaultCredentials;
request.MaximumAutomaticRedirections = 4;
localFileName = Path.GetFileName(localFileName);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Stream receiveStream = response.GetResponseStream();
string newPath = Path.Combine(tempFold, localFileName);
using (FileStream fs = new FileStream(newPath, FileMode.Create))
{
Byte[] buffer = new Byte[4096];
int bytesRead = receiveStream.Read(buffer, 0, buffer.Length);
while (bytesRead > 0){
fs.Write(buffer, 0, bytesRead);
bytesRead = receiveStream.Read(buffer, 0, buffer.Length);
}
}
receiveStream.Close();
}
private static void RunFile(string dir, string localFileName){
string info = "运行程序" + localFileName;
try{
if (File.Exists(Path.Combine(dir, localFileName))){
Process myProcess = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = localFileName;
psi.WorkingDirectory = dir;
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;
psi.WindowStyle = ProcessWindowStyle.Hidden;
myProcess.StartInfo = psi;
myProcess.Start();
string error = myProcess.StandardError.ReadToEnd();
string output = myProcess.StandardOutput.ReadToEnd();
myProcess.WaitForExit();
myProcess.Close();
if (error != string.Empty){
Log.Write("StandardError:" + error);
}
if (output != string.Empty){
Log.Write("StandardOutput:" + output);
}
Log.LogProcessEnd(info);
}
}
catch (Exception ex){
Log.Write(info + "出错");
Log.LogException(ex);
throw ex;
}
}
}
2。部分更新,比较适合大程序,大程序可能每次更新都下载完整文件,所以需要做版本比较后,确认需要更新的文件,然后按需下载,然后启动更新,替换本地文件后,启动程序;次方法可以解决大体积程序下载过慢的问题,减少服务器的流量负担,一般的商业系统都是此类方法。