Update.asmx仅提供一个功能,就是检测是否需要更新,在需要更新的时候就返回一个更新地址,通常情况下返回的地址就是Download.ashx,而在某些特殊情况下,也可以修改服务端使之从其他Url提供更新下载。检测是否需要更新的的具体做法是:首先获取Updata目录中的主程序版本号,再获取数据库中的最新版本号,两者对比。如果相同则直接与客户端提供的版本号相对比并返回结果;如果不同则将主程序版本号写入数据库,然后生成新的更新文件包,直接向客户端返回更新地址。

Download.ashx的功能仅仅是将最新版本更新文件包输出。

而客户端部分包含主程序、Update.exe以及其他附属文件,更新时由主程序检测并下载更新,在主程序退出时,如有更新并已成功下载,则调用Update.exe完成解包及更新覆盖工作。需注意的是:Update.exe永远不能被更新,因为它无法更新其自身,所以服务端更新时也不要将Update.exe纳入更新包。

下面就是来实际编写一个自动更新解决方案:

服务器端

首先建立一个Web服务项目,项目名为“自动更新服务”:

添加一数据库,名为Database.mdf:

在数据库中创建新的数据库关系图,并如下设计数据库表:

创建一个Ado.Net Entity Data Model,名为Model.edmx:

从刚才的建立的数据库中生成模型:

在Web.Config的appSettings节点中新增两个节点,用以设置更新程序的主文件名及更新包下载地址:

C# code复制代码
<appSettings><add key="主程序文件名" value="MyApp.exe"/><add key="更新包下载地址" value="Download.ashx"/>
</appSettings>

引入一个GZip类用以打包(该类的源码将在文章末尾随本文示例源代码一并提供):

添加一个新的Web服务,名为Update.asmx:

书写如下代码:

C# code复制代码
[WebMethod]
public string GetUpdate(string ClientVerison)
{if (获取最新版本() != ClientVerison){return System.Web.Configuration.WebConfigurationManager.AppSettings["更新包下载地址"];}return null;
}static string 获取最新版本()
{string v = 获取文件版本(HttpContext.Current.Server.MapPath(string.Format("~/App_Data/Update/{0}", System.Web.Configuration.WebConfigurationManager.AppSettings["主程序文件名"])));using (var c = new DatabaseEntities()){//从数据库取得最新版本信息var q = c.UpdateVersion.OrderByDescending(f => f.PublicTime).FirstOrDefault();if (q == null || v != q.Version){//数据库中的版本与当前主程序版本不一致时,以主程序版本为准,写入数据库,并生成新的更新文件包var d = new UpdateVersion() { Version = v, PublicTime = DateTime.Now };c.AddToUpdateVersion(d);c.SaveChanges();打包更新文件(HttpContext.Current.Server.MapPath("~/App_Data/Update/"), HttpContext.Current.Server.MapPath("~/App_Data/Update.gzip"));}}return v;
}public static void 打包更新文件(string 打包目录, string 输出文件)
{GZip.压缩(输出文件, Directory.GetFiles(打包目录).Concat(Directory.GetDirectories(打包目录)).ToArray());
}public static string 获取文件版本(string 文件路径)
{FileVersionInfo f = FileVersionInfo.GetVersionInfo(文件路径);return f.FileVersion;
}

创建Download.ashx,用以输出更新文件包:

代码:

C# code复制代码
public void ProcessRequest(HttpContext context)
{context.Response.ContentType = "application/zip";context.Response.WriteFile(context.Server.MapPath("~/App_Data/Update.gzip"));
}

服务端至此就编写完毕了。

客户端

新建一个WinForm应用程序项目,名为Update:

建好之后直接删掉Form1.cs吧,此程序不需要界面,在Program.cs中写代码就可以了。

同样需要引入GZip类用于解包:

然后编写代码:

C# code复制代码
[STAThread]
static void Main()
{try{var d = DateTime.Now;while (DateTime.Now.Subtract(d).TotalSeconds < 10) Application.DoEvents();GZip.解压缩(Path.Combine(Application.StartupPath, "update.data"), Application.StartupPath);}catch { }
}

这里的作用就是等待10秒,然后解包update.data文件,覆盖到当前目录中。

现在来建立主程序,主程序是WinForm、命令行、WPF都可以,我们新建一个WPF应用程序,命名为MyAPP:

为程序添加服务引用:

这里的地址使用的是本地的调试地址。

为了检测主程序自身的版本号,还需要添加对System.Windows.Forms的引用。

然后开始设计界面,这里仅为演示更新操作,所以界面上只是简单的设计了更新相关的提示、操作控件:

代码为:

需注意的是,这里控件都被设置为Visibility="Hidden",我们将会在需要时再将其显示出来。

编写后台代码:

C# code复制代码
public Uri DownloadUri
{get{return _DownloadUri;}set{_DownloadUri = value;}
}
private Uri _DownloadUri;public bool UpdateReady
{get{return _UpdateReady;}set{_UpdateReady = value;}
}
private bool _UpdateReady;private void Window_Loaded(object sender, RoutedEventArgs e)
{var u = new MyApp.ServiceReference.UpdateSoapClient();var s=u.GetUpdate(System.Windows.Forms.Application.ProductVersion);if (!string.IsNullOrEmpty(s)){//获取相对于Web服务所在Uri的UriDownloadUri = new Uri(u.Endpoint.ListenUri, s);label1.Visibility = button1.Visibility = Visibility.Visible;}
}private void button1_Click(object sender, RoutedEventArgs e)
{var c = new WebClient();c.DownloadFile(DownloadUri, System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "update.data"));UpdateReady = true;label2.Visibility = Visibility.Visible;
}private void Window_Closed(object sender, EventArgs e)
{if (UpdateReady){Process.Start(System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "update.exe"));}
}

测试

现在将主程序、附属文件和Update.exe放在一起,并将主程序及附属文件复制一份放到服务器端的App_data/Update/目录中,再添加一个“更新说明.txt”:

然后启动客户端程序进行测试,应该看到程序界面里什么都没有,因为客户端和服务器端程序版本是一致的。

现在我们修改客户端版本号为1.0.0.1:

然后重新编译程序。

因为服务器仅仅是判断版本号是否不同,而不是哪个更高,所以不仅仅是升级,降级更新也是可以的,我们来测试一下:

找到所谓的新版本了^^,点开始下载:

下载完成,这时目录里就有update.data这个文件了。

现在关闭程序,等待10秒,让Update.exe完成更新:

可以看到,程序被降级为1.0.0.0了,而且那个“更新说明.txt”也被更新出来了。

C# 实现软件自动更新升级程序相关推荐

  1. C#软件自动更新程序

    2019独角兽企业重金招聘Python工程师标准>>> 基于C#实现的软件自动更新程序,之前在网上搜集了两款软件自动更新程序,在实际应用中,对部分BUG进行修复,添加+完善一些功能. ...

  2. android应用程序的自动更新升级(自身升级,通过tomcat),[SaltStack] Minion-conf自动更新...

    minion-conf配置文件自动更新, 加载 minion-conf是每个minion自身以来的配置, 为了方便我们在中心管控机上(Master)统一配置, 然后下发文件, 进而使得Minion能够 ...

  3. 用C#实现C/S模式下软件自动在线升级[转载]

    摘要: 本文针对目前C/S模式下编写的应用程序可维护性差的特点,提出了一套自动在线升级的解决方案,分析了在线升级的困难及实现原理,并给出了实现升级的部分代码,具有实际参考价值和现实意义.本文程序代码均 ...

  4. 用C#实现软件自动更新

    IT实验室 1 前言 长期以来,广大程序员为到底是使用Client/Server,还是使用Browser/Server结构争论不休,在这些争论当中,C/S结构的程序可维护性差,布置困难,升级不方便,维 ...

  5. [转载]C#实现软件自动更新思路

    转自:IT实验室 1 前言 长期以来,广大程序员为到底是使用Client/Server,还是使用Browser/Server结构争 论不休,在这些争论当中,C/S结构的程序可维护性差,布置困难,升级不 ...

  6. 软件自动更新功能的实现

    今天一朋友在群里面问,软件自动更新功能怎么做,大家都不知道怎么搞,我下午刚好没事情,就研究了下. 附上我的源代码 考虑下基本的思路 1 .客户端(主程序)调用升级程序,升级程序连接到最新的服务器上. ...

  7. python更新pip失败-解决Python pip 自动更新升级失败的问题

    在使用python pip的时候,经常会发生pip版本过低导致失败的情况,这时候,系统会提示让你使用如下命令对pip进行升级更新: python -m pip install --upgrade pi ...

  8. 软件自动更新解决方案及QT实现

    from:https://blog.csdn.net/hulinhulin/article/details/46839107 软件自动更新解决放案及QT实现...1 1 文件的版本控制-XML.2 2 ...

  9. 如何屏蔽 iOS 16 软件自动更新,去除更新通知和标记

    如何禁用 iPhone.iPad 软件自动更新.适用于 iOS.iPadOS 和 watchOS,即 iPhone.iPad 和 Apple Watch 通用. 请访问原文链接:https://sys ...

最新文章

  1. sftp进入指定目录_CentOS7服务搭建----搭建SFTP(安全文件传送协议)服务器
  2. rocketMq - commitLog
  3. 【吐血推荐】领域驱动设计学习输出
  4. 第一章:渗透测试之信息搜集
  5. DAVINCI DM365-368中 linux-2.6.32的移植
  6. lenos快速开发脚手架
  7. delphi中Label中文显示不全的问题解决办法
  8. java 导出表 sql_java中把SQL数据库中的表导出到excel中.怎么实现
  9. Swift - whose view is not in the window hierarchy 问题解决方法
  10. shell 截取ip地址最后一位_shell脚本获取IP地址段的方法
  11. 《数据结构与算法》——线性表之顺序表(SqList)总结
  12. 小马哥----高仿机部分6735芯片机型的root方法浅析 高仿三星Galaxy S6 A228_4G刷机root
  13. Java判断时间在5分钟的之内方法
  14. Ubuntu 开机自动开启数字键小键盘
  15. 【工程师笔记】第六期:一项Xeon E5-2600 v4测试数据的背后
  16. MATLAB小技巧整理-那些你必须得知道的matlab技巧
  17. Multisim 实验 2.0.1 逻辑门电路 PPT
  18. InputStream输入字节流
  19. maven自定义依赖并推送到远程仓库
  20. 心理励志,激活生命的潜能

热门文章

  1. 常用技巧 —— 位运算
  2. 图论 —— 图的连通性 —— Tarjan 缩点
  3. 级数求和(信息学奥赛一本通-T1087)
  4. 63 SD配置-交货凭证配置-定义交货的项目类别
  5. 快速排序 java代码_java实现快速排序
  6. Windows10远程桌面连接提示:出现身份验证错误,要求的函数不受支持
  7. 使用Origin Pro2021画简单函数图像
  8. numpy 中np.max--求序列的最大值和np.maximum--X和Y逐位进行比较,选择最大值
  9. 超分辨率技术,随机噪声
  10. [Matlab] 符号积分求对流扩散方程在给定初始条件下的一维解