实现原理:通过一个辅助程序(更新程序.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客户端自动升级的更多相关文章

  1. NetworkComms 文件上传下载和客户端自动升级(非开源)

    演示程序下载地址:http://pan.baidu.com/s/1geVfmcr 淘宝地址:https://shop183793329.taobao.com 联系QQ号:3201175853 许可:购 ...

  2. 分享一个客户端程序(winform)自动升级程序,思路+说明+源码

    做winform的程序,不管用没用过自动更新,至少都想过自动更新是怎么实现的. 我这里共享一个自动更新的一套版本,给还没下手开始写的人一些帮助,也希望有大神来到,给指点优化意见. 本初我是通过sock ...

  3. 黄聪:C#Winform程序如何发布并自动升级(图解)

    有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...

  4. 【转】C#Winform程序如何发布并自动升级(图解)

    有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...

  5. 自动升级系统OAUS的设计与实现(续) (附最新源码)

    (最新OAUS版本请参见:自动升级系统的设计与实现(续2) -- 增加断点续传功能) 一.缘起 自从 自动升级系统的设计与实现(源码) 发布以后,收到了很多使用者的反馈,其中最多的要求就是希望OAUS ...

  6. Android 实现应用升级方案(暨第三方自动升级服务无法使用后的解决方案)

    第三方推送升级服务不再靠谱: 以前在做Android开发的时候,在应用升级方面都是使用的第三方推送升级服务,但是目前因为一些非技术性的问题,一些第三方厂商不再提供自动升级服务,比如友盟,那么当第三方推 ...

  7. c/s 自动升级(WebService)

    首先声明,本人文笔不好,大家见笑,欢迎高手吐槽. 做c/s开发肯定会遇到的就是自动升级功能,而这实现方式是非常多. 本文使用 webservice的方式来提供升级服务 首先准备服务 为了方便我们专门用 ...

  8. java CS结构软件自动升级的实现

    前段时间做了一个工具发布给公司的各部门使用后反馈了不少BUG,每次修改后均需要发邮件通知各用户替换最新版本,很不方便,因此后来就写了一个自动升级的功能,这样每次发布新的版本时只需要将其部署到自动升级服 ...

  9. 在WinForm中使用Web Service来实现软件自动升级

    来源:互联网 winform程序相对web程序而言,功能更强大编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题,在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术 ...

随机推荐

  1. 数论-质因数(gcd) UVa 10791 - Minimum Sum LCM

    https://vjudge.net/problem/UVA-10791/origin 以上为题目来源Google翻译得到的题意: 一组整数的LCM(最小公倍数)定义为最小数,即 该集合的所有整数的倍 ...

  2. Daily Scrum 12/24/2015

    Process: Zhaoyang: Some UI change and compile the Caffe in the IOS. Yandong: Do some code integratio ...

  3. 学会这项python技能,就再也不怕孩子偷偷打游戏了

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:鸟哥 PS:如果想了解更多关于python的应用,可以私信小编,资料 ...

  4. Laravel Passport token过期后判断refresh_token是否过期

    需求:前后端分离状态下,登录失效(token过期)后,前端需要知道下一步是跳转到登录页面还是使用refresh_token刷新token. 这就需要后端根据是否可以刷新token(refresh_to ...

  5. 13.create-react-app 构建的项目使用代理 proxy

    1. 正常运行 npm run eject 2. create-react-app 的版本在低于 2.0 的时候可以在 package.json 增加 proxy 配置, 配置成如下: "p ...

  6. java算法-二分法查找实现

    什么是二分法查找 首先,使用二分法查找的前提是:被查找的数组已排好序 具体实现: 假如有一组数为3,12,24,36,55,68,75,88要查给定的值24.可设三个变量front,mid,end分别 ...

  7. SpringCloud-Alibaba-Nacos 服务注册中心&配置中心

    Spring Cloud Alibaba 由于 Spring Cloud Netflix 项目进入维护模式(将模块置于维护模式意味着 Spring Cloud 团队将不会再向模块中添加新功能,只会修复 ...

  8. 关于flex弹性布局

    http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

  9. Display a QMessageBox from a QThread

    Emit a signal. Since you cannot do UI stuff in a Qthread, instead send your message as an argument o ...

  10. Spring5参考指南:容器扩展

    文章目录 BeanPostProcessor自定义bean BeanFactoryPostProcessor自定义配置元数据 使用FactoryBean自定义实例化逻辑 Spring提供了一系列的接口 ...