首页 > 其他分享 >.NET实现之(自动更新

.NET实现之(自动更新

时间:2022-11-29 18:01:30浏览次数:35  
标签:文件 GetDictiory 实现 更新 Util 自动更新 NET down


 

​​.NET实现之(自动更新)​​


2011-05-13 13:23 by 南京.王清培, 3005 visits, ​​网摘​​, ​​收藏​​, ​​编辑​​

做开发的人,尤其是做客户端(C/S)系统开发的人都会遇到一个头疼的问题,就是软件的自动更新;系统发布后怎样自动的更新程序,在下有幸开发过一个自动更新程序,更新程序与任何宿主程序是完全独立的;只要在主程序里面启动更新程序就行了;更新程序也是一个可执行文件,在启动的时候可以设置是否是自动更新和是否是手动更新,自动更新的意思就是说不需要人工的干预实现从远程服务器下载更新包,而如果是手动更新就会涉及到用户点击程序中的按钮实现更新;在自动更新与手动更新中可以根据项目的需要进行选择,有的程序必须要求用户进行更新才能继续使用,所以程序自动更新是有必要的;手动更新就是用户可以随时更新程序,不需要严格的控制版本问题;下面本人就来讲一下具体的实现细节,我贴出部分代码,源码属公司财产本人不宜上传;

自动更新的目的就是将服务器上的DLL文件拷贝到本地执行目录中,并且覆盖本地同名的文件;流程很简单,但是实现起来有几个地方需要注意:

1.大批量的DLL文件怎么下载到本地来,有多个DLL文件在下载过程中如果网速慢的情况下可能出现丢包、丢文件等情况;本人的实现是将多个文件通过ICSharpCode.SharpZipLib组件进行打包,这样可以省很多事;(如:动态连接库文件dll的名称在传输过程中大小写可能会变化)

2.下载到本地了,怎么覆盖原有的同名文件;本人的实现是先同名的文件的支持删除,然后解压缩;这个过程需要临时保存删除的文件,防止操作失败程序无法启动,要注意有事务性的原理;

3.如果更新的文件不只是单单的DLL文件可能还有一些无限极的文件夹;本人的实现是如果存在同名的文件夹,直接递归的删除,然后将其解压缩到目录中;由于压缩包解压后的顶级目录是压缩文件的名称,所有在复制的过程中需要注意目录的层次关系;

下面我们来走一下实现的整个流程,虽然没有给出整个源码,但是如果看完这篇文章的你基本实现起来没什么大问题了;

为了部署方便我建议大家麻烦点实现一个部署文件的工具,将所有的文件直接打包在里面同时生成服务器端的版本信息文件;

.NET实现之(自动更新_.net

利用这个工具就很方便的实现了对文件进行压缩、生成HASH值、版本文件、更新地址等信息;

.NET实现之(自动更新_数据结构_02

这个XML中保存的是服务当前的版本信息、更新文件的名称、更新文件的HASH值,为什么需要HASH就是怕更新文件在某些情况下被人调包了,如果所有的客户端更新后后果很严重;所以我们必须带上HASH值;

.NET实现之(自动更新_.net_03

.NET实现之(自动更新_XML_04

工具生成两个文件,一个是版本文件一个是更新包,服务器的任务已经完成,下面就是具体的客户端的实现;

为了知道何时需要进行版本更新所以要在客户端程序目录中保存一份用来记录版本信息的文件;

.NET实现之(自动更新_XML_05

文件中保存着当前本地的版本号、服务器的更新地址、宿主程序的名称,需要宿主的名称就能在更新的时候将宿主程序重进程中枚举出来然后关掉,这样就不影响我们更新了,当然也可以实现宿主程序不关闭的情况下更新,如果用到某些已经被宿主程序占用的情况会直接影响更新流程,所以以防万一关了为妙;

.NET实现之(自动更新_.net_06

这是客户端版本文件中保存的信息;

我们上面说了,更新分为手动和自动,我们先来说手动更新吧,手动更新就是需要用户自己去点击更新按钮然后开始更新,这个问题我们可以利用进程的参数传递解决;

.NET实现之(自动更新_应用服务器_07

当然在更新程序里面需要有这方面的逻辑判断;

.NET实现之(自动更新_XML_08

入口的地方我们进行判断,更新方式;这里的下载远程更新包是用WebClient对象,也可以用其他的基于Socket的对象;更新开始之前需要先判断本地的版本号是否小于远程版本号,如果小于在进行更新;

.NET实现之(自动更新_Socket_09

因为下载的过程是异步的所以需要用到后台线程建议大家使用System.ComponentModel.BackgroundWorker这个后台线程对象,他对Thread进行了很好的封装;下面来看一下核心的流程代码:

01  //开始辅助线程操作
02 private void Back_thread_DoWork(object sender, DoWorkEventArgs e)
03 {
04 try
05 {
06 //实例化下载对象
07 downclient = new WebClient();
08 downclient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(downclient_DownloadProgressChanged);
09 downclient.DownloadFileCompleted += new AsyncCompletedEventHandler(downclient_DownloadFileCompleted);
10 //下载远程更新包down.zip压缩文件|放在应用程序目录下|相应界面事件
11 downclient.DownloadFileAsync(new Uri(Util.GetUpdateUrl() + "down.zip"), Util.GetDictiory() + "\\down.zip");
12 }
13 catch (Exception err) { System.Diagnostics.Debug.WriteLine(err); }
14 }
15 //在异步下载结束时触发该事件
16 void downclient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
17 {
18 try
19 {
20
21 if (e.Error != null)
22 {
23 eventLog1.WriteEntry(e.Error.ToString());
24 MessageBox.Show("在进行远程更新时,发生错误", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
25 }
26 else
27 {
28 Util.KillProcess();//关闭主进程
29 //验证哈希值
30 if (Util.IsHash(Util.GetHash(Util.GetDictiory() + "\\down.zip"), FileWork.GetDownHash()))
31 {
32 //删除无用压缩文件
33 File.Delete(Util.GetDictiory() + "\\down.zip");
34 //删除无用版本文件
35 File.Delete(Util.GetDictiory() + "\\ServerUpdateFiles.xml");
36 MessageBox.Show("远程服务器更新包已发生变化,无法更新", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
37 eventLog1.WriteEntry("远程服务器中的更新包在制作和下载时间段中数据包发生变化,为了安全期间不给予下载!");
38 this.Close();
39 }
40 else
41 {
42 //解压压缩包文件
43 ReduceToUnReduceFile.unZipFile(Util.GetDictiory() + "\\down.zip", Util.GetDictiory());
44 //删除压缩包文件
45 File.Delete(Util.GetDictiory() + "\\down.zip");
46 //检查文件夹层次结构
47 FileWork.LookFiles(Util.GetDictiory() + "\\down", Util.GetDictiory());
48 //订阅复制文件事件
49 FileWork.CopyFileEvent += new FileWork.CopyFileDelegate(FileWork_CopyFileEvent);
50 //递归复制文件
51 FileWork.CopyFiles(Util.GetDictiory() + "\\down", Util.GetDictiory());
52 //删除临时文件夹
53 FileWork.DeleteFiles(Util.GetDictiory() + "\\down");
54 //如果库结构更新成功,则才能更新程序的版本号,否则下次继续更新
55 if (EventChainReference.GlobalEventChain.OnAutoUpdateDb())
56 //更新本地版本号信息
57 Util.UpdateLocalXml();
58 File.Delete(Util.GetDictiory() + "\\ServerUpdateFiles.xml");
59
60 MessageBox.Show("升级成功!", "信息提示");
61 Util.StartProcess();
62 isupdate = true;
63
64 }
65 }
66 }
67 catch (Exception err) { eventLog1.WriteEntry(err.ToString()); }
68 Application.Exit();
69 }

这部分代码是串联整个过程的代码;

自动更新大概就讲完了,几个关键的地方都给出了,希望对大家开发自动更新程序有帮助;


标签:文件,GetDictiory,实现,更新,Util,自动更新,NET,down
From: https://blog.51cto.com/u_15834343/5896210

相关文章

  • 栈实现计算器的操作
    栈实现计算器的操作使用一个栈完成计算一个表达式的结果使用两个栈:数栈(存放数)符号栈(存放运算符)思路通过一个index值,来遍历我们的表达式如果我们发现一个数字,......
  • C# 数据库访问通用类 (ADO.NET)
    SqlDbHelper.csviewsourceprint?001usingSystem;002usingSystem.Collections.Generic;003usingSystem.Text;004usingSystem.Data;005usingSystem.Data.SqlClien......
  • Kubernetes初探[1]:部署您的第一个ASP.NET Core应用到k8s集群
    Kubernetes简介Kubernetes是Google基于Borg开源的容器编排调度引擎,作为CNCF(CloudNativeComputingFoundation)最重要的组件之一,它的目标不仅仅是一个编排系统,而是提供一......
  • .Net Core中自定义认证实现
    一、起因最近项目中需要对项目同时支持JWT认证,以及自定义的认证校验方式认证。通过对官方文档了解,得到认证实现主要通过继承 IAuthenticationHandler 或 Authenticat......
  • 小程序发现新版本后自动更新
    当小程序发布新版本后,客户端每次启动后检查当前小程序是否是最新版本,如果不是则提示更新。onLaunch(){console.log('AppLaunch')functiondownLoadAndUpdate(upda......
  • NetwoekManger之nmcli
    nmcliconnectionshow #查看网卡启用状态 nmcliconnectionmodifyenp216s0f0ipv4.methodmanualipv4.addresses10.10.1.12/24 ipv4.gateway10.10.1.10ipv4.d......
  • CefSharp 实现下载功能
    CefSharp能在C#winform中实现浏览器功能同样的在浏览器中网页上如果有下载按钮实现下载功能直接上代码CefSharp在winform上实现浏览器功能usingSystem;......
  • 防抖节流的区别 怎么实现防抖节流
    防抖节流区别 怎么实现的 防抖:指在触发事件后n秒内函数只执行一次(确定不在更改时执行)如果在n秒内再次被触发则时间会被重新计算如:王者里面的回城如果回城终端......
  • .net如何优雅的使用EFCore
    .net如何优雅的使用EFCore EFCore是微软官方的一款ORM框架,主要是用于实体和数据库对象之间的操作。功能非常强大,在老版本的时候叫做EF,后来.netcore问世,EFCore也随之......
  • 我开发的开源项目,让.NET7中的EFCore更轻松地使用强类型Id
    在领域驱动设计(DDD)中,有一个非常重要的概念:“强类型Id”。使用强类型Id来做标识属性的类型会比用int、Guid等通用类型能带来更多的好处。比如有一个根据根据Id删除用户的方......