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程序而言,功能更强大编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题,在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术 ...
随机推荐
- Java编程最差实践常见问题详细说明(1)转
Java编程最差实践常见问题详细说明(1)转 原文地址:http://www.odi.ch/prog/design/newbies.php 每天在写Java程序, 其实里面有一些细节大家可能没 ...
- C++_编程前奏
计算机硬件系统 计算机操作系统的五大组成部分 计算机操作系统的组成部分 构成 控制器 指令寄存器(IR)/程序计数器(PC)/操作控制器(OC) 运算器 算数逻辑单元/累加器/状态寄存器/通用寄存器 ...
- bootstrapTable随机改变列颜色
{ title: '运单编号', field: 'waybillNumber', align: 'center', valign: 'middle', cellStyle: function (val ...
- 004-流程控制-C语言笔记
004-流程控制-C语言笔记 学习目标 1.[掌握]关系运算符和关系表达式 2.[掌握]逻辑运算符和逻辑表达式 3.[掌握]运算符的优先级和结合性 4.[掌握]if-else if-else结构的使用 ...
- vue2.x学习笔记(九)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12577948.html. 数组的更新检测 数组在javascript是一种特殊的对象,不是像普通的对象那样通过Ob ...
- 3. pkg
程序打包成可执行文件(.exe) 1.) npm install -g pkg 2.) 单个文件:pkg entrance.js ( windows: pkg -t win entrance.js ...
- 2020i春秋新春战疫
简单的招聘系统 登陆这里就可以注入 查询这里也可以注入 从登陆这里注入把 爆破数据库名 爆破表名 列名 flag 就很奇怪跑出来的东西 重开容器跑一遍列,估计是flaaag.后面可能是发生了502 再 ...
- 【认证与授权】2、基于session的认证方式
这一篇将通过一个简单的web项目实现基于Session的认证授权方式,也是以往传统项目的做法. 先来复习一下流程 用户认证通过以后,在服务端生成用户相关的数据保存在当前会话(Session)中,发给客 ...
- 可以用 Python 编程语言做哪些神奇好玩的事情?除了生孩子不能,其他全都行!
坦克大战 源自于一个用Python写各种小游戏的github合集,star数1k.除了坦克大战外,还包含滑雪者.皮卡丘GOGO.贪吃蛇.推箱子.拼图等游戏. 图片转铅笔画 帮助你快速生成属于自己的铅笔 ...
- [Hands-on-Machine-Learning-master] 02 Housing
用到的函数 numpy.random.permutation随机排列一个序列,返回一个排列的序列. >>> np.random.permutation(10) array([1, 7 ...