实现原理:通过一个辅助程序(更新程序.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. JS获取链接中的参数

    /*获取当前页面链接中的参数*/ function GetQueryString(name) { var reg = new RegExp("(^|&)" + name + ...

  2. VulnHub靶场学习_HA: Avengers Arsenal

    HA: Avengers Arsenal Vulnhub靶场 下载地址:https://www.vulnhub.com/entry/ha-avengers-arsenal,369/ 背景: 复仇者联盟 ...

  3. AJ整理问题之:内存堆栈

    内存 数据在内存中的存放 在计算机中,运行的应用程序的数据都是保存在内存中的. 不同类型的数据,保存的内存区域不同,其中包括: 1:栈区(stack)由编译器自动分配并释放,一半存放函数的参数值,局部 ...

  4. 原创hadoop2.6集群环境搭建

    三台机器: Hmaster 172.168.2.3.Hslave1 172.168.2.4.Hslave2 172.168.2.6 JDK:1.8.49 OS:red hat 5.4 64 (由于后期 ...

  5. 【学习笔记】 $learn \ from \ failure \ ? ( 雾$

    \(1.\)变量名不要用 \(next\) ,在某些编译器里可能是关键词,可以用 \(nxt\) 代替 \(\\\) \(2.\)在判断某些条件时应该写成 flag = 条件 ? 1 : flag; ...

  6. 如何使用IE9浏览器自带开发人员工具捕获网页请求

    我们在通过浏览器访问一个网页的时候,有时候会遇到页面不能正常显示,图片不能正常加载的问题. 如果我们需要知道浏览器打开该网页时,网页中每个元素的加载情况.这时,我们便可以借助浏览器自带开发人员工具,来 ...

  7. java redis面试专题(附答案)

    1.什么是Redis?简述它的优缺点? Redis的全称是:Remote Dictionary.Server,本质上是一个Key-Value类型的内存数据库,很像 memcached,整个数据库统统加 ...

  8. 3、flink架构,资源和资源组

    一.flink架构 1.1.集群模型和角色 如上图所示:当 Flink 集群启动后,首先会启动一个 JobManger 和一个或多个的 TaskManager.由 Client 提交任务给 JobMa ...

  9. python-trade

    https://tool.lu/pyc/在线反编译pyc import base64 correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt' flag = base64.b6 ...

  10. 2018 ICPC Pacific Northwest Regional Contest I-Inversions 题解

    题目链接: 2018 ICPC Pacific Northwest Regional Contest - I-Inversions 题意 给出一个长度为\(n\)的序列,其中的数字介于0-k之间,为0 ...