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程序而言,功能更强大编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题,在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术 ...
随机推荐
- hibernate.current_session_context_class 比较权威的解释
hibernate.current_session_context_class 博客分类: hibernate HibernateSpring多线程配置管理thread 遇到过的问题: 情景1: 在 ...
- 数据结构和算法(Golang实现)(5)简单入门Golang-接口
接口 在Golang世界中,有一种叫interface的东西,很是神奇. 一.数据类型 interface{} 如果你事前并不知道变量是哪种数据类型,不知道它是整数还是字符串,但是你还是想要使用它. ...
- 数据结构和算法(Golang实现)(26)查找算法-哈希表
哈希表:散列查找 一.线性查找 我们要通过一个键key来查找相应的值value.有一种最简单的方式,就是将键值对存放在链表里,然后遍历链表来查找是否存在key,存在则更新键对应的值,不存在则将键值对链 ...
- 基于linux或windows的c/s的循环服务器求一元二次方程的根
在linux和windows上实现 c/s模式 socket循环服务器求解一元二次方程的根 ax^2+bx+c=0 根据上式,客户端发送a,b,c给服务器,返回求解的根 暂未考虑非法数据等问题 lin ...
- PDF各种骚操作如何用python实现
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: wLsq PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- Java匹马行天下之JavaSE核心技术——异常处理
Java匹马行天下之JavaSE核心技术——异常处理 异常的简介 在Java中,异常就是Java在编译.运行或运行过程中出现的错误. 程序错误分为三种:编译错误.运行时错误和逻辑错误 编译错误是因为程 ...
- docx4j docx转html
不好用,转完问题挺多,百度还找不到资料头疼.public static void docxToHtml(String fileUrl) throws Exception { String path = ...
- Oracle数据库提权
一.执行java代码 简介 oracle提权漏洞集中存在于PL/SQL编写的函数.存储过程.包.触发器中.oracle存在提权漏洞的一个重要原因是PL/SQL定义的两种调用权限导致(定义者权限和调用者 ...
- 2020.4面试分享(7面收割5个offer)
都说金三银四是找工作的最佳时节,由于本人的个人职业规划跟目前工作内容不太相符(具体原因就不透露了,领导平时也要来这里逛,哈哈),四月份挑选了10多家公司投递简历(公司规模从几十人到上万人都有),参加了 ...
- Python flask 构建可扩展的restful ap
Flask-RESTful是flask的扩展,增加了对快速构建REST API的支持. Flask-RESTful通过最少的设置鼓励最佳的实践. pip install flask-restfulFl ...