本文将演示一种桌面程序自动更新方案,其步骤比较多,但原理非常简单,通用性尚可,对于小型应用来说,直接拿去就可以用了。

原理

服务器端的结构是这样的:

其工作原理如下:

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节点中新增两个节点,用以设置更新程序的主文件名及更新包下载地址:

  1. <appSettings>
  2. <add key="主程序文件名" value="MyApp.exe"/>
  3. <add key="更新包下载地址" value="Download.ashx"/>
  4. </appSettings>

复制代码

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

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

书写如下代码:

  1. [WebMethod]
  2. public string GetUpdate(string ClientVerison)
  3. {
  4. if (获取最新版本() != ClientVerison)
  5. {
  6. return System.Web.Configuration.WebConfigurationManager.AppSettings["更新包下载地址"];
  7. }
  8. return null;
  9. }
  10. static string 获取最新版本()
  11. {
  12. string v = 获取文件版本(HttpContext.Current.Server.MapPath(string.Format("~/App_Data/Update/{0}", System.Web.Configuration.WebConfigurationManager.AppSettings["主程序文件名"])));
  13. using (var c = new DatabaseEntities())
  14. {
  15. //从数据库取得最新版本信息
  16. var q = c.UpdateVersion.OrderByDescending(f => f.PublicTime).FirstOrDefault();
  17. if (q == null || v != q.Version)
  18. {
  19. //数据库中的版本与当前主程序版本不一致时,以主程序版本为准,写入数据库,并生成新的更新文件包
  20. var d = new UpdateVersion() { Version = v, PublicTime = DateTime.Now };
  21. c.AddToUpdateVersion(d);
  22. c.SaveChanges();
  23. 打包更新文件(HttpContext.Current.Server.MapPath("~/App_Data/Update/"), HttpContext.Current.Server.MapPath("~/App_Data/Update.gzip"));
  24. }
  25. }
  26. return v;
  27. }
  28. public static void 打包更新文件(string 打包目录, string 输出文件)
  29. {
  30. GZip.压缩(输出文件, Directory.GetFiles(打包目录).Concat(Directory.GetDirectories(打包目录)).ToArray());
  31. }
  32. public static string 获取文件版本(string 文件路径)
  33. {
  34. FileVersionInfo f = FileVersionInfo.GetVersionInfo(文件路径);
  35. return f.FileVersion;
  36. }

复制代码

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

代码:

  1. public void ProcessRequest(HttpContext context)
  2. {
  3. context.Response.ContentType = "application/zip";
  4. context.Response.WriteFile(context.Server.MapPath("~/App_Data/Update.gzip"));
  5. }

复制代码

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

客户端

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

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

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

然后编写代码:

  1. [STAThread]
  2. static void Main()
  3. {
  4. try
  5. {
  6. var d = DateTime.Now;
  7. while (DateTime.Now.Subtract(d).TotalSeconds < 10) Application.DoEvents();
  8. GZip.解压缩(Path.Combine(Application.StartupPath, "update.data"), Application.StartupPath);
  9. }
  10. catch { }
  11. }

复制代码

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

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

为程序添加服务引用:

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

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

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

代码为:

  1. <Window x:Class="MyApp.Window1"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="Window1" Height="300" Width="377" Loaded="Window_Loaded" Closed="Window_Closed">
  5. <Grid>
  6. <Grid.RowDefinitions>
  7. <RowDefinition Height="1*" />
  8. <RowDefinition Height="1*" />
  9. <RowDefinition Height="1*" />
  10. </Grid.RowDefinitions>
  11. <Label Margin="0" Name="label1" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden">检测到新版本,是否下载?</Label>
  12. <Button Grid.Row="1" Height="23" Name="button1" VerticalAlignment="Center" Visibility="Hidden" Click="button1_Click">开始下载</Button>
  13. <Label Grid.Row="2" Margin="0" Name="label2" VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="Hidden">更新包已下载完毕,在程序关闭后将自动执行更新操作。</Label>
  14. </Grid>
  15. </Window>

复制代码

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

编写后台代码:

  1. public Uri DownloadUri
  2. {
  3. get
  4. {
  5. return _DownloadUri;
  6. }
  7. set
  8. {
  9. _DownloadUri = value;
  10. }
  11. }
  12. private Uri _DownloadUri;
  13. public bool UpdateReady
  14. {
  15. get
  16. {
  17. return _UpdateReady;
  18. }
  19. set
  20. {
  21. _UpdateReady = value;
  22. }
  23. }
  24. private bool _UpdateReady;
  25. private void Window_Loaded(object sender, RoutedEventArgs e)
  26. {
  27. var u = new MyApp.ServiceReference.UpdateSoapClient();
  28. var s=u.GetUpdate(System.Windows.Forms.Application.ProductVersion);
  29. if (!string.IsNullOrEmpty(s))
  30. {
  31. //获取相对于Web服务所在Uri的Uri
  32. DownloadUri = new Uri(u.Endpoint.ListenUri, s);
  33. label1.Visibility = button1.Visibility = Visibility.Visible;
  34. }
  35. }
  36. private void button1_Click(object sender, RoutedEventArgs e)
  37. {
  38. var c = new WebClient();
  39. c.DownloadFile(DownloadUri, System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "update.data"));
  40. UpdateReady = true;
  41. label2.Visibility = Visibility.Visible;
  42. }
  43. private void Window_Closed(object sender, EventArgs e)
  44. {
  45. if (UpdateReady)
  46. {
  47. Process.Start(System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "update.exe"));
  48. }
  49. }

复制代码

测试

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

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

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

然后重新编译程序。

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

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

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

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

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

转载于:https://www.cnblogs.com/guoqiao/archive/2010/08/17/1801444.html

Winform窗体应用程序的自动更新功能相关推荐

  1. Android 程序自动更新功能模块实现

    2019独角兽企业重金招聘Python工程师标准>>> Android 程序自动更新功能模块实现 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程 ...

  2. android自动更新demo,Android程序自动更新功能模块的实现方法【附完整demo源码下载】...

    本文实例讲述了Android程序自动更新功能模块的实现方法.分享给大家供大家参考,具体如下: 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程序启动的时候首先调用更 ...

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

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

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

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

  5. 4步彻底关闭win10的自动更新功能

    4步彻底关闭win10的自动更新功能,请按下面4步逐一操作 一.禁用Windows Update服务 按下键盘 Win + R,打开运行对话框,然后输入命令 services.msc ,点击下方的&q ...

  6. 怎么禁用Opera浏览器的自动更新功能

    2019独角兽企业重金招聘Python工程师标准>>> 怎么禁用Opera浏览器的自动更新功能 2016年07月12日 08:33:01 vic-chen 阅读数:5052更多 个人 ...

  7. 如何刷新微信服务器小程序版本,微信小程序版本自动更新

    最近在做一个小程序每次更新版本之后都需要删除小程序,再次扫码进入才可以看到新版本,接下来吾爱编程为大家介绍一下微信小程序版本自动更新的方法,有需要的小伙伴可以参考一下: 1.启动机制: (1).热启动 ...

  8. android 360自动更新,Android应用自动更新功能的实现!!!

    大家好,发现半年没有更新博客了,最近一直都比较忙,决定在凌晨 英超 阿森纳VS富勒姆 中场休息的时候,给大家分享Android里应用版本更新功能这一块的实现. 一个好的应用软件都是需要好的维护,从初出 ...

  9. java 自动检查更新去掉勾,小熊纯净版Win10旗舰版如何关闭java自动更新功能

    我们在win10电脑店专业版系统上面安装了JAVA JRE或JDK后,就会启动一个jusched,它会定时检查更新,每次开机都会推荐更新或者升级,可能有的朋友在win10下无论如何都关不掉java客户 ...

最新文章

  1. UITableView 添加长按手势UILongPressGestureRecognizer
  2. 揭晓飞桨平台提速秘诀:INT8量化加速实现“事半功倍”
  3. 【linux排错】error while loading shared libraries: xxx.so.x 错误的原因和解决办法
  4. 启明云端分享|SSD201_自动升级固件与烧录MAC地址
  5. 04_Weblogic之受管服务器:配置受管服务器,启动受管服务器,解决因为强制关闭Weblogic之后导致启动有问题的问题,配置boot.properties
  6. 试图安装客户出现SSR问题的Spartacus Storefront时遇到的错误消息
  7. 【模板】最大密度子图
  8. python 当前时间的前一天_Python与Stata的数据交互
  9. 鸿蒙系统翻车了,鸿蒙“翻车”? 网友发现鸿蒙系统居然是安卓9.0
  10. 10本入门编程书籍推荐,带你入门到精通
  11. 信息加工心理学用计算机的工作原理,第四章 认知学习理论 第七节 信息加工学习理论...
  12. window10刷新卡顿
  13. 雷锋科普:联发科MT6577,国产平民双核手机的芯
  14. 深入理解JVM - 类文件的结构
  15. Linux界面和字体大小调整
  16. 1800 Flying to the Mars 大数 最多不上升序列 简化题意
  17. 一键关机 / 重启脚本
  18. 靠谱的录屏软件 + mp4格式转换软件
  19. 开关量、数字量、模拟量、脉冲量的区别
  20. 【Win10错误】从0x80190001错误码恢复

热门文章

  1. guice google_与Google Guice的动手实践
  2. fiddler使用技巧进阶,如何抓包修改数据?——AutoResponder重定向
  3. php pthread 实例,php 真正的多线程 pthread
  4. php 多条数据更新数据类型,PHPdoc @param中的两个或多个数据类型
  5. 关于高速光耦6n137的使用总结_光耦使用中的那点事1
  6. 详解数组中的reduce方法
  7. @芥末的糖----------《后端加密》
  8. JS-DOM-元素节点
  9. Android官方开发文档Training系列课程中文版:OpenGL绘图之应用投影与相机视图
  10. 【原】YUI压缩与CSS media queries下的bug