winform(C#)程序实现在线更新软件
有winform程序 LWH.exe,现需要实现远程升级功能,参考网上的相关方案实现步骤如下:
1、在远程服务器上建立FTP站点,将更新文件及更新信息放到相关文件夹中
其中,updates.json内容如下:
{ "latestversion": "3.0.3", "downloadurl": "http://***.***.***.***:****/lwh/update303.zip", "changelog": "更改注册机制", "mandatory": true }
latestversion代表提供更新的版本号,downloadurl表示更新包的下载路径,这里将需要更新的文件压缩成zip文件
update303.zip即为需要更新的文件
2、在工程下App.config中添加key为Version的字段来表示当前软件版本号
<configuration> ... <appSettings> <add key="Version" value="3.0.2" /> </appSettings> </configuration>
在生成的文件中该.config对应的是 应用程序名.exe.config,比如我的应用程序 是LWH.exe,则在打包更新包时应将LWH.exe.config一起打包,这样更新完软件后,软件版本号则更新到新的版本号
程序中获取当前版本号的代码为:
version = System.Configuration.ConfigurationManager.AppSettings["Version"].ToString();
3、在解决方案中,新建一个winform应用项目update,用以从服务器上下载更新包,并解压到指定文件夹替换相关文件实现更新
放置一个progressBar用来表示下载进度,放置一个label用来进行提示,代码如下:
private string url;//下载路径 public static FastZip fz = new FastZip(); public update(string[] args) { InitializeComponent(); if (args == null || args.Count() == 0) url = "http://***.***.***.***:**/lwh/update.zip";//没有传入地址时使用默认地址 else url = args[0]; } private void update_Load(object sender, EventArgs e) { updateprocess(); } private void updateprocess() { try { WebClient wc = new WebClient(); wc.DownloadProgressChanged += wc_DownloadProgressChanged; wc.DownloadFileAsync(new Uri(url), Application.StartupPath + "\\update.zip"); } catch(Exception er) { label1.Text = "下载失败:"+er.Message; } } private void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { Action act = () => { this.progressBar1.Value = e.ProgressPercentage; this.label1.Text = "正在下载..."; //this.label1.Text = e.ProgressPercentage + "%"; }; this.Invoke(act); if (e.ProgressPercentage == 100) { //下载完成之后开始覆盖 this.label1.Text = "正在解压..."; try { var result = Compress(Application.StartupPath, Application.StartupPath + "\\update.zip",null); //var result = unZip(Application.StartupPath + "\\update.rar", @"..\LWH\"); if (result== "Success!") { progressBar1.Value = 100; this.label1.Text = "准备安装..."; //备份之前数据库 var dbFile = Application.StartupPath + "/Data/TestDb.db"; if (File.Exists(dbFile)) { var bakFile = Application.StartupPath + "/backup/" + DateTime.Now.ToString("yyyyMMddHHmmssms") + ".bak"; var bakDirectory = Path.GetDirectoryName(bakFile); DirectoryInfo directoryInfo = new DirectoryInfo(bakDirectory); if (!directoryInfo.Exists) { directoryInfo.Create(); } else { //删除7天前的备份文件 var files = directoryInfo.GetFiles(); if (files != null && files.Length > 0) { foreach (var file in files) { if (file.CreationTime.AddDays(7) < DateTime.Now) { file.Delete(); } } } } //备份文件 File.Move(dbFile, bakFile); } this.label1.Text = "更新完成"; var mainFile =Application.StartupPath+"/LWH.exe";//重新启动软件 Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = mainFile; p.StartInfo.CreateNoWindow = true; p.Start(); this.Close(); } else { MessageBox.Show("更新失败:"+result); this.Close(); } } catch (Exception ex) { MessageBox.Show("更新失败", ex.Message); this.Close(); } } } /// <summary> /// 解压Zip /// </summary> /// <param name="DirPath">解压后存放路径</param> /// <param name="ZipPath">Zip的存放路径</param> /// <param name="ZipPWD">解压密码(null代表无密码)</param> /// <returns></returns> public string Compress(string DirPath, string ZipPath, string ZipPWD) { string state = "Fail!"; try { fz.Password = ZipPWD; fz.ExtractZip(ZipPath, DirPath, ""); state = "Success!"; } catch (Exception ex) { state += "," + ex.Message; } return state; }
4、将生成的update.exe拷贝到主应用程序(LWH.exe)软件目录下以供调用,在LWH的检测更新按键下加入以下代码:
private void buttonXUpdate_Click(object sender, EventArgs e) { try { string rXml = string.Empty; HttpWebRequest myHttpWebRequest = System.Net.WebRequest.Create(backdata.updateUrl) as HttpWebRequest; myHttpWebRequest.KeepAlive = false; myHttpWebRequest.AllowAutoRedirect = false; myHttpWebRequest.UserAgent = "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)"; myHttpWebRequest.Timeout = 5000; myHttpWebRequest.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; using (HttpWebResponse res = (HttpWebResponse)myHttpWebRequest.GetResponse()) { if (res.StatusCode == HttpStatusCode.OK || res.StatusCode == HttpStatusCode.PartialContent)//返回为200或206 { string dd = res.ContentEncoding; System.IO.Stream strem = res.GetResponseStream(); System.IO.StreamReader r = new System.IO.StreamReader(strem); rXml = r.ReadToEnd(); } else { MessageBox.Show("无法连接到远程服务器"); return; } } updateInf updateinf = JsonConvert.DeserializeObject<updateInf>(rXml); if (string.Compare(updateinf.latestversion, version) > 0) { if (MessageBox.Show("有新版本:" + updateinf.latestversion + "\r\n" + "更新内容:" + updateinf.changelog + "\r\n是否进行更新?", "提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { return; } var mainFile = Application.StartupPath + @"\update.exe"; Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = mainFile; p.StartInfo.CreateNoWindow = true; p.StartInfo.Arguments = updateinf.downloadurl; p.Start(); this.Close(); } else { MessageBox.Show("没有更新版本了!"); } } catch(Exception er) { MessageBox.Show("检查更新出现错误:" + er.Message); } }
updateInf为定义的更新文件信息类:
public class updateInf { public string latestversion; public string downloadurl; public string changelog; public string mandatory; }
点击“检查更新”按键后,首先从服务器读取updates.json,解析出服务器上的版本号和当前软件的版本进行比对,如果比当前版本新,则提示进行更新,如果选择进行更新则启动update.exe并传入updates.json中提供的更新包下载地址,启动后立即关闭主程序。
最后,可以对update稍作修改,在启动的时候传入参数中再增加exe名称,如
public update(string[] args) { InitializeComponent(); if (args == null || args.Count() < 2) { //url = "http://116.63.143.64:9010/lwh/update.zip"; } else { url = args[0]; exename = args[1]; } }
升级完毕时,重启程序 改成:
if (exename != "") { var mainFile = Application.StartupPath +"/"+ exename; Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = mainFile; p.StartInfo.CreateNoWindow = true; p.Start(); this.Close(); }
这就可以将update很便捷地添加到其他工程里面实现远程升级功能
引用:https://blog.csdn.net/luckyzjian/article/details/108421143