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

原理

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

其工作原理如下:

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

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

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

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

书写如下代码:

[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,用以输出更新文件包:

代码:

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类用于解包:

然后编写代码:

[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的引用。

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

代码为:

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

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

编写后台代码:

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”也被更新出来了。

下载

示例源代码:http://www.uushare.com/user/icesee/file/2338431

本文的XPS版本:http://www.uushare.com/user/icesee/file/2338436

本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2009/12/21/1628566.html,如需转载请自行联系原作者

简单的自动更新程序实现相关推荐

  1. 艾伟_转载:简单的自动更新程序实现

    本文将演示一种桌面程序自动更新方案,其步骤比较多,但原理非常简单,通用性尚可,对于小型应用来说,直接拿去就可以用了. 原理 服务器端的结构是这样的: 其工作原理如下: Update.asmx仅提供一个 ...

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

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

  3. 如何制作自动更新程序?

    原文出自:http://blog.csdn.net/metaphysis/article/details/18866631 如何制作自动更新程序? [版权所有 邱秋 2014 metaphysis@y ...

  4. C# WINFORM的自动更新程序

    自动更新程序AutoUpdate.exe https://git.oschina.net/victor596jm/AutoUpdate.git 1.获取源码 http://git.oschina.ne ...

  5. python自动更新程序

    简介 windows 自动更新程序 最近用python给开发了一个windows监控软件,用于监控电脑的运行情况,更新电脑软件.由于有几十电脑,一台一台手动更新就不太靠谱了,于是就开发了一个自动更新软 ...

  6. 【原创】自动更新程序2--更新程序的主窗体(技术:spring.net+三层架构+webservice+IrisSkin2换肤)...

    上篇文章主要介绍了webservice的部署以及主要的代码,下面给大家贴上主程序的代码,并简单的讲解.主程序判断是否有更新时通过主程序目录下有一个update.ini文件内的version是否有变化, ...

  7. 我的软件之自动更新程序

    实现升级程序自身升级和更新主程序: 主要逻辑:主程序启动---主程序检测到新版本---主程序退出,启动升级程序--升级程序启动---检测升级程序自身版本---发现升级程序新版本---重命名升级程序-- ...

  8. c#自动更新+安装程序的制作

    一.自动更新的实现 让客户端实现自动更新,通常做法是在客户端部署一个单独的自动更新程序.主程序启动后,访问服务端,检查配置文件是 否有更新版本,有更新版本就启动更新程序,由更新负责下载更新版本,并更新 ...

  9. 用计算机升级ipad系统软件,iPad怎么设置软件程序自动更新?

    现在各种软件也是推陈出新,为了适应最新的系统.潮流,每隔一段时间都会有更新.不想错过的朋友,可以在你的iPad上设置自动更新. 1.看到iPad上面的app store常年有个右上角的数字,强迫症的人 ...

最新文章

  1. 生成窄带信号_房间冲激响应RIR原理与模拟生成方法
  2. LVS学习笔记--概念
  3. 算法提高课-图论-单源最短路的建图方式-AcWing 1129. 热浪:dijkstra裸题
  4. JAVA基础知识(1)
  5. vc实现透明位图,透明背景
  6. linux乌邦图更改ip,Linux系统下图形界面更改IP地址分享
  7. if var matlab,matlab中if 语句后面的判别式不能是算术表达式?或者说变量?
  8. Python 学习第三部分函数——第一章函数基础
  9. 得到选择框句柄 怎么操作_电脑版微信怎么多开?最简单的三种电脑版微信多开教程...
  10. pipedreader_Java PipedReader ready()方法与示例
  11. GRIDVIEW排序 动态实现和静态实现
  12. OculusQuest2 直接连电脑调试
  13. 如何在结构体里面套结构体_Rust 学习笔记-13 Rust 结构体
  14. php微信公众号测试号token配置失败,微信公众号Token配置失败解决办法
  15. Android Studio “Project Structure”选项目录结构显示异常
  16. 济南python工资一般多少-Python火到天际,可是为啥找工作这么难?
  17. python selenium点击网页关闭按钮_基于python的selenium-打开关闭第二个页面
  18. Java Web开发流程
  19. 中国31省R&D经费支出、R&D投入强度数据(2000-2018年)
  20. IntelliJ IDEA 常用快捷键 ------ Windows / Mac 对比

热门文章

  1. 遍历窗体中所有控件的信息
  2. 安卓系统开机过程中logo和动画
  3. oracle 一些基本概念
  4. qsort的7种用法(转)
  5. Qomolangma实现篇(三):兼容层设计
  6. python3 多继承搜索__init__方法的两种策略
  7. 蛮力法在查找算法中的应用(JAVA)--顺序查找
  8. python tfidf特征变换_Spark MLlib机器学习开发指南(4)--特征提取--TF-IDF
  9. lstm网络_LSTM(长短期记忆网络)
  10. android webview 获取 title,【报Bug】app webview 安卓机 title显示问题