WPF客户端自动升级
实现原理:通过一个辅助程序(更新程序.exe)比较本地版本号和服务器的版本,若服务器版本新则通过更新程序.exe下载服务器上资源(我是把最新的文件压缩成zip放到服务器上)到本地进行替换。
服务器放置的升级文件结构如图
- 此时要有两个程序,一个是自己的主程序,另一个是更新程序.exe,更新程序负责检查版本号和下载更新,将更新程序放到主程序的目录下。
- 在主程序界面渲染显示前,调用更新程序.exe进行版本检查,如果有新版本则进行更新,没有的话主程序继续执行。
- 此时本地和服务器应该有个相同的配置文件,用来存放一些必需的数据,我这里用的xml文件,读取本地xml文件和服务器xml文件,比较版本信息(指的是主程序version和更新程序version)进而判断需要升级主程序或者是升级程序亦或两者都升级。
- 如果发现主程序有新版本,启用更新程序.exe从服务器上下载Debug.zip文件及xml文件,将zip压缩包放到临时文件夹下,利用第三方解压库CL.IO.Zip.dll进行解压,解压完成后将解压得到的文件夹及文件递归复制到主程序目录下,然后在更新程序中用Process.Start(主程序路径)启动主程序,主程序启动成功则关闭更新程序.exe程序(可以通过杀进程操作),此时软件已经升级成功。(这里我主程序只是做了版本比较,至于下载以及升级都交给更新程序.exe来做,当然也可以通过主程序进行下载,感觉有点分散了。。。)
- 如果发现更新程序.exe有新版本,则直接在主程序中下载更新程序.exe进行替换即可。
- 两者都有最新版本,先按照第4步升级更新程序.exe,在按照第3步升级主程序。
部分压缩包下载及解压代码:
public class DownloadHelper
{
/// <summary>
/// 获取版本信息
/// </summary>
/// <param name="url">版本信息文件的url</param>
/// <returns></returns>
public static Tuple<bool,UpdateInfo> GetConfigInfo(string url)
{
try
{
if (string.IsNullOrEmpty(url))
{
return new Tuple<bool, UpdateInfo>(false, null);
}
WebClient client = new WebClient();
Stream s = client.OpenRead(new Uri(url));
UpdateInfo info = XmlHelper.Instance.ReadVersionConfig(s);
s.Close();
return new Tuple<bool,UpdateInfo>(true,info);
}
catch (Exception)
{
return new Tuple<bool, UpdateInfo>(false, null);
}
}
/// <summary>
/// 解压缩,拷贝,删除
/// </summary>
/// <param name="sourcePath">zip的路径</param>
/// <param name="targetPath">目的路径</param>
/// <returns></returns>
public static bool UnZip(string sourcePath, string targetPath)
{
try
{
string zipFile = Path.Combine(sourcePath, "temp.zip");
string extractPath = Path.Combine(targetPath, "temp");
if (!Directory.Exists(extractPath))
{
Directory.CreateDirectory(extractPath);
}
ZipFile.ExtractToDirectory(zipFile, extractPath);//将zip文件拷贝到临时文件夹
if (Directory.Exists(Path.Combine(extractPath, "SeriesApp")))
{
extractPath = Path.Combine(extractPath, "SeriesApp");
}
//将临时文件夹下的文件复制到原程序路径中
CopyDirectory(extractPath, sourcePath);//注意,此时临时文件夹为源地址,sourcePath为目标地址
File.Delete(zipFile);//删除zip文件
Directory.Delete(Path.Combine(targetPath, "temp"), true);
return true;
}
catch (Exception)
{
return false;
}
} /// <summary>
/// 解压缩,拷贝,删除
/// </summary>
/// <param name="sourcePath">zip的路径</param>
/// <param name="targetPath">目的路径</param>
/// <param name="pBar">ProgressBar显示进度</param>
/// <returns></returns>
public static bool UnZip(string sourcePath, string targetPath,System.Windows.Controls.ProgressBar pBar)
{
try
{
ZipHandler handler = ZipHandler.GetInstance();
string zipFile = Path.Combine(sourcePath, "temp.zip");
string extractPath = Path.Combine(targetPath, "temp");
handler.UnpackAll(zipFile, extractPath, (num) =>
{
pBar.Dispatcher.Invoke(() =>
{
pBar.Value = num;//进度条显示
});
}); if (Directory.Exists(Path.Combine(extractPath, "SeriesApp")))
{
extractPath = Path.Combine(extractPath, "SeriesApp");
}
//将临时文件夹下的文件复制到原程序路径中
CopyDirectory(extractPath, sourcePath);//注意,此时临时文件夹为源地址,sourcePath为目标地址
File.Delete(zipFile);//删除zip文件
Directory.Delete(Path.Combine(targetPath, "temp"), true);
return true;
}
catch (Exception ex)
{
return false;
}
}
/// <summary>
/// 下载zip文件
/// </summary>
/// <param name="zipUrl">zip的url</param>
/// <param name="targetDirPath">目标文件夹路径</param>
/// <returns></returns>
public static bool DownloadZip(string zipUrl,string targetDirPath)
{
string zipFile = Path.Combine(targetDirPath, "temp.zip");
if (!Directory.Exists(targetDirPath))
{
return false;
}
try
{
WebClient client = new WebClient();
client.DownloadFile(new Uri(zipUrl), zipFile);
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 下载xml配置
/// </summary>
/// <param name="url"></param>
/// <param name="targetPath"></param>
/// <returns></returns>
public static bool DownLoadXMLConfig(string url, string targetPath)
{
try
{
var xmlPath = Path.Combine(targetPath, "VersionConfig.xml");
WebClient client = new WebClient();
client.DownloadFile(new Uri(url), xmlPath);
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 获取Zip的总大小
/// </summary>
/// <param name="zipUrl"></param>
/// <returns></returns>
public static double GetZipTotalSize(string zipUrl)
{ try
{
WebClient client = new WebClient();
byte[] sr = client.DownloadData(new Uri(zipUrl));
return sr.Length;
}
catch (Exception)
{
return ;
}
}
/// <summary>
/// 递归copy文件
/// </summary>
/// <param name="sourcePath"></param>
/// <param name="targetPath"></param>
private static void CopyDirectory(string sourcePath, string targetPath)
{
try
{
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
string[] files = Directory.GetFiles(sourcePath);//Copy文件
foreach (string file in files)
{
try
{
string pFilePath = targetPath + "\\" + Path.GetFileName(file);
File.Copy(file, pFilePath, true);
}
catch (Exception)
{
continue;
}
} string[] dirs = Directory.GetDirectories(sourcePath);//Copy目录
foreach (string dir in dirs)
{
CopyDirectory(dir, targetPath + "\\" + Path.GetFileName(dir));
}
}
catch (Exception ex)
{ }
}
}
WPF客户端自动升级的更多相关文章
- NetworkComms 文件上传下载和客户端自动升级(非开源)
演示程序下载地址:http://pan.baidu.com/s/1geVfmcr 淘宝地址:https://shop183793329.taobao.com 联系QQ号:3201175853 许可:购 ...
- 分享一个客户端程序(winform)自动升级程序,思路+说明+源码
做winform的程序,不管用没用过自动更新,至少都想过自动更新是怎么实现的. 我这里共享一个自动更新的一套版本,给还没下手开始写的人一些帮助,也希望有大神来到,给指点优化意见. 本初我是通过sock ...
- 黄聪:C#Winform程序如何发布并自动升级(图解)
有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...
- 【转】C#Winform程序如何发布并自动升级(图解)
有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...
- 自动升级系统OAUS的设计与实现(续) (附最新源码)
(最新OAUS版本请参见:自动升级系统的设计与实现(续2) -- 增加断点续传功能) 一.缘起 自从 自动升级系统的设计与实现(源码) 发布以后,收到了很多使用者的反馈,其中最多的要求就是希望OAUS ...
- Android 实现应用升级方案(暨第三方自动升级服务无法使用后的解决方案)
第三方推送升级服务不再靠谱: 以前在做Android开发的时候,在应用升级方面都是使用的第三方推送升级服务,但是目前因为一些非技术性的问题,一些第三方厂商不再提供自动升级服务,比如友盟,那么当第三方推 ...
- c/s 自动升级(WebService)
首先声明,本人文笔不好,大家见笑,欢迎高手吐槽. 做c/s开发肯定会遇到的就是自动升级功能,而这实现方式是非常多. 本文使用 webservice的方式来提供升级服务 首先准备服务 为了方便我们专门用 ...
- java CS结构软件自动升级的实现
前段时间做了一个工具发布给公司的各部门使用后反馈了不少BUG,每次修改后均需要发邮件通知各用户替换最新版本,很不方便,因此后来就写了一个自动升级的功能,这样每次发布新的版本时只需要将其部署到自动升级服 ...
- 在WinForm中使用Web Service来实现软件自动升级
来源:互联网 winform程序相对web程序而言,功能更强大编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题,在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术 ...
随机推荐
- 数据结构和算法(Golang实现)(7)简单入门Golang-标准库
使用标准库 一.避免重复造轮子 官方提供了很多库给我们用,是封装好的轮子,比如包fmt,我们多次使用它来打印数据. 我们可以查看到其里面的实现: package fmt func Println(a ...
- qt creator源码全方面分析(4-1)
目录 d指针和q指针 简单示例 q指针 QObject和QObjectPrivate qtcreator中的变体1 qtcreator中的变体2 小结 d指针和q指针 我们在类成员名称和使用d指针中, ...
- MDC是什么鬼?用法、源码一锅端
近期用到阿里的一款开源的数据同步工具 Canal,不经意之中看到了 MDC 的用法,而且平时项目中也多次用到 MDC,趁机科普一把. 通过今天的分享,能让你轻松 get 如下几点,绝对收获满满. a) ...
- Spring5:面向切面
静态代理 缺点:一个真实角色就会产生一个代理角色,代码量会翻倍! 场景:要在写好的实现方法上加入日志功能(公共功能),不要修改原代码 1:原代码 业务接口: package com.spring; p ...
- react: typescript custom hooks useAsyncTable
define basic data: const SET_QUERY = "SET_QUERY"; const TOGGLE_LOADING = "TOGGLE_LOAD ...
- pytorch 手写数字识别项目 增量式训练
dataset.py ''' 准备数据集 ''' import torch from torch.utils.data import DataLoader from torchvision.datas ...
- coding++:@DisallowConcurrentExecution 注解的作用
Quartz定时任务默认都是并发执行的,不会等待上一次任务执行完毕,只要间隔时间到就会执行, 如果定时任执行太长,会长时间占用资源,导致其它任务堵塞. 在Spring中这时需要设置concurrent ...
- Zabbix备份数据文件
mysql自带的工具mysqldump,当数据量大了之后进行全备所花的时间比较长,这样将会造成数据库的锁读.从而zabbix服务的监控告警不断,想着做下配置文件的备份.刚好有这么个脚本.满足了需求. ...
- 闲置安卓设备搭建Linux服务器实现外网访问
title: 闲置安卓设备搭建Linux服务器实现外网访问 这是我搭过的第一个博客系统,写贴纪念一下 待博主整理好思路,将今天所用到的全部分享! 好吧,我就是穷.富人靠科技,穷人靠变异.我这种穷人是真 ...
- 更加安全的密钥生成方法Diffie-Hellman
更加安全的密钥生成方法Diffie-Hellman 之前我们谈到了密钥配送的问题,这个世界是如此的危险, 一不小心通信线路就会被监听,那么我们怎么在这种不安全的线路中传递密钥呢? 这里我们介绍一下Di ...