本通用自动更新模块适合所有Windows桌面程序的自动更新,不论语言,无论Winform还是wpf。

一、工作流程:
1. 主程序A调起升级程序B
2. B从服务器获取更新程序列表,打印更新信息。
3. B杀死A进程(此步骤可以放在步骤2~5任意位置)
4. B根据更新信息中指示的地址,下载更新程序包(.zip文件)
5. 解压缩.zip文件到一个新创建的文件夹
6. 将解压后的文件拷贝到原始文件目录,做替换。
7. 删除下载的.zip文件以及解压后创建的文件夹
8. B打开A

二、源码介绍:

升级程序B的实现:

更新信息列表用于存储版本信息,以及更新说明信息。通常为json或xml文件。本文为json文件。

存储列表信息的类

public class UpdateItem
{
public string Version { get; set; } //版本号
public string UpdateContent { get; set; } //更新信息
public string DownloadUri { get; set; } //更新包的下载地址
public string Time { get; set; } //更新时间
public string Size { get; set; } //更新包大小
}

获取更新信息使用WebClient.DownloadData(Uri),其中使用Newtonsoft.Json进行json序列化及反序列化。

WebClient client = new WebClient();
byte[] data = client.DownloadData(uri);
//json转为UpdateItem类对象
UpdateInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<UpdateItem>(Encoding.UTF8.GetString(data));

获取更新信息以后在界面上进行输出。
下面介绍一下生成更新信息的json文件并使用FTP上传到服务器的代码。json文件也可以手动写,手动上传。不是重点,不想看可以跳到下一部分。

UpdateItem UpdateInfo = new UpdateItem();
... //赋值
string json = JsonConvert.SerializeObject(UpdateInfo);
//连接服务器
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://...");
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("账号", "密码");
// 复制字符
byte[] fileContents = Encoding.UTF8.GetBytes(json);
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();

下载更新包zip文件

下载使用WebClient.DownloadFile(Uri, string)

string dir = System.IO.Directory.GetCurrentDirectory();  //程序所在文件夹路径
string zipfile = System.IO.Path.Combine(dir, "file.zip"); //下载后zip文件的完整路径 WebClient client = new WebClient();
client.DownloadFile(UpdateInfo.DownloadUri, zipfile);
return true;

解压缩zip文件

解压缩需要用到System.IO.Compression.ZipFile,需要.NET4.5及以上。如果用不了(找不到ZipFile),请检查是否已添加引用System.IO.Compression.FileSystem程序集。

代码只有一行,两个参数分别为zip文件完整路径,解压后的文件夹完整路径。

ZipFile.ExtractToDirectory(zipfile, extractPath);

使用第三方压缩软件生成的.zip文件有可能会解压失败,建议使用下方代码生成。两个参数分别为需要压缩的文件夹完整路径,生成的zip文件完整路径。

ZipFile.CreateFromDirectory(startPath, zipfile);

拷贝解压后的文件到原始目录

foreach (string item in Directory.GetFiles(extractPath))
{
File.Copy(item, System.IO.Path.Combine(dir, System.IO.Path.GetFileName(item)), true);
}

删除临时文件

File.Delete(zipfile);
DirectoryInfo di = new DirectoryInfo(extractPath);
di.Delete(true);

B进程杀死A进程

string appname = "file"; //A名字,不要路径,不要.exe
Process[] processes = Process.GetProcessesByName(appname);
foreach (var p in processes)
p.Kill();

B进程调起A进程

System.Diagnostics.Process.Start(@"path");  //完整路径

主要流程就是这些,建议用异步操作实现。
现在上号比较少,私信很多要代码的都没回…以后都会把完整代码附上的。
下面是完整代码。

private Uri uri = new Uri(@"http://...");  //更新信息列表文件路径
private UpdateItem UpdateInfo; //UpdateItem类的定义在前面第一部分说明 public MainWindow()
{
InitializeComponent();
LoadingData();
} //用户按下更新按钮
private async void Button_Click(object sender, RoutedEventArgs e)
{
//下载
Tb_State.Text = "正在下载新版本文件,请耐心等待";
string dir = System.IO.Directory.GetCurrentDirectory();
string zipfile = System.IO.Path.Combine(dir, "File.zip");
bool success = await Task.Run(() =>
{
try
{
WebClient client = new WebClient();
client.DownloadFile(UpdateInfo.DownloadUri, zipfile);
return true;
}
catch (Exception)
{
return false;
}
}); if (success)
Tb_State.Text = "文件已下载,正在复制文件";
else
{
Tb_State.Text = "下载新版本文件失败,请重试";
return;
} //杀死主程序进程
string appname = "File";
Process[] processes = Process.GetProcessesByName(appname);
foreach (var p in processes)
p.Kill(); //解压缩+拷贝+删除
bool success2 = await Task.Run(() =>
{
try
{
string extractPath = System.IO.Path.Combine(dir, "NewVersion");
ZipFile.ExtractToDirectory(zipfile, extractPath);
foreach (string item in Directory.GetFiles(extractPath))
File.Copy(item, System.IO.Path.Combine(dir, System.IO.Path.GetFileName(item)), true);
File.Delete(zipfile);
DirectoryInfo di = new DirectoryInfo(extractPath);
di.Delete(true);
return true;
}
catch (Exception)
{
return false;
}
}); if (success2)
Tb_State.Text = "更新完成,您可以点击下方按钮启动应用";
else
Tb_State.Text = "复制更新文件出错,请重试";
} //读取更新列表文件
private async Task<bool> LoadingData()
{
Tb_State.Text = "正在下载更新文件信息";
bool success = await Task.Run(() =>
{
try
{
WebClient client = new WebClient();
byte[] data = client.DownloadData(uri);
UpdateInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<UpdateItem>(Encoding.UTF8.GetString(data));
return true;
}
catch (Exception)
{
return false;
}
}); if (success)
Tb_State.Text = "已获取新版本信息,可进行更新";
else
Tb_State.Text = "无法获取更新信息";
return success;
} //更新完成,更新程序B调起主程序A
private void Btn_Open_Click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Process.Start(@"D:\..."); //A程序完整路径
}

再贴一个用于下载过程中,能实时显示已下载文件大小的代码
此部分需写在下载部分之前。

System.Windows.Threading.DispatcherTimer dt = new System.Windows.Threading.DispatcherTimer();
dt.Interval = TimeSpan.FromMilliseconds(100); //100毫秒
dt.Tick += (x, y) => {
if (File.Exists(zipfile) == false)
return;
string size = ((new FileInfo(zipfile).Length) / 1024.0 / 1024).ToString("f2");
if (download == false) //是否下载完毕
Tb_State.Text = size + "MB / " + UpdateInfo.Size; //输出:已下载/总大小
else
dt.Stop();
};
dt.Start();

代码部分执行时,再次执行代码可能会报错。可能原因包括下载zip文件后未删除再次下载报错等。如要做项目还有很多地方需要进行判断,如检测路径的合法性等。为了代码便于阅读,没有加入这些错误检测部分,需自行补充。几乎所有操作前都应判断路径合法性,以及目标位置的文件是否存在(是否需要先删除)等。只能说是在输入合法的情况下,完整执行此代码是没有问题的。

代码通过Visual Studio 2019测试,.NET4.5。

Windows程序通用自动更新模块(C#,.NET4.5以上)的更多相关文章

  1. Winform开发框架之通用自动更新模块(转)

    在网络化的环境中,特别是基于互联网发布的Winform程序,程序的自动更新功能是比较重要的操作,这样可以避免挨个给使用者打电话.发信息通知或者发送软件等,要求其对应用程序进行升级.实现程序的自动更新, ...

  2. winform 通用自动更新程序

    通用自动更新程序 主要功能: 1. 可用于 C/S 程序的更新,集成到宿主主程序非常简单和配置非常简单,或不集成到主程序独立运行. 2. 支持 HTTP.FTP.WebService等多种更新下载方式 ...

  3. WinForm通用自动更新器AutoUpdater项目实战

    一.项目背景介绍 最近单位开发一个项目,其中需要用到自动升级功能.因为自动升级是一个比较常用的功能,可能会在很多程序中用到,于是,我就想写一个自动升级的组件,在应用程序中,只需要引用这个自动升级组件, ...

  4. 分析nuget源码,用nuget + nuget.server实现winform程序的自动更新

    源起 (个人理解)包管理最开始应该是从java平台下的maven开始吧,因为java的开发大多数是基于开源组件开发的,一个开源包在使用时很可能要去依赖其他的开源包,而且必须是特定的版本才可以.以往在找 ...

  5. Android应用程序的自动更新升级(自身升级、通过tomcat)(转)

    Android应用程序的自动更新升级(自身升级.通过tomcat) http://blog.csdn.net/mu0206mu/article/details/7204746 刚入手android一个 ...

  6. 【实用篇】Android之应用程序实现自动更新功能

    我个人用的是友盟提供的自动更新组件,因此在这里只描述如何实用友盟提供的组件来完成程序的自动更新,步骤如下: 1.登录友盟官网,点击注册一个友盟账号. 2.注册成功后将会自动进入到添加新应用界面,选择添 ...

  7. 安卓程序代写 网上程序代写[原]Android应用的自动更新模块

    软件的自动更新一般都与Splash界面绑定在一起, 由于需要维护的软件界面很复杂, 一个Activity中嵌入ViewPager, 并且逻辑比较复杂, 索性重新写一个Activity, 现在的软件都很 ...

  8. windows下svn自动更新

    配置hooks下post-commit.bat文件,文件内容如下 @echo offSET REPOS=%1SET REV=%2SET DIR=%REPOS%/hooksSET PATH=%PATH% ...

  9. 【Android 应用开发】Android应用的自动更新模块

    . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . 软件的自动更新一般都与Splash界 ...

随机推荐

  1. Java中instanceof注意的地方

    instanceof只能用于对象的判断,不能用于基本类型的判断,以下代码会编译不通过 'A' instanceof Character instanceof特有的规则:若左操作数是null,结果就直接 ...

  2. JAVA基础学习1

    一.JAVA是一种具有多种功能的高级语言:1,可以用于开发web页面上的小程序,桌面上运行的应用程序: 2,用于客户端服务器资源通讯的服务器端中间件: 3,还可以用于web服务器. 二.程序设计的5个 ...

  3. ADF 第五篇:转换数据

    映射数据流(Mapping Data Flow)的核心功能是转换数据,数据流的结构分为Source.转换和Sink(也就是Destination),这种结构非常类似于SSIS的数据流. 在数据流中,数 ...

  4. c预处理和宏

    文件的预处理 #include "xxx.h" 1 首先查找当前源文件所在的路径 2 查找工程的头文件搜索路径 #include <xxxx.h> 查找工程的头文件搜索 ...

  5. 面试 02-CSS盒模型及BFC

    02-CSS盒模型及BFC #题目:谈一谈你对CSS盒模型的认识 专业的面试,一定会问 CSS 盒模型.对于这个题目,我们要回答一下几个方面: (1)基本概念:content.padding.marg ...

  6. eclipse中字体、XML字体设置

    [修改编辑区中文字体大小]: Window > Preferences > General > Appearance > Colors and Fonts > Java ...

  7. JPDA 远程调试方法记录

    一.JPDA概念 JPDA(Java platform debugger architecture)是java平台调试架构的简称,由java虚拟机后端和调试平台前端组成. 1.java虚拟机提供了ja ...

  8. ElasticSearch设置用户名密码访问

    版本号:7.3.1 1.需要在配置文件中开启x-pack验证, 修改config目录下面的elasticsearch.yml文件,在里面添加如下内容,并重启. xpack.security.enabl ...

  9. MM-合作伙伴确定过程

    第一步:物料管理---采购---合作伙伴确定---合作伙伴角色---定义合作伙伴角色. 第二步:物料管理---采购---合作伙伴确定---合作伙伴角色---定义每个科目组适合的合作伙伴角色. 第三步: ...

  10. [leetcode]516. Longest Palindromic Subsequence最大回文子序列

    Given a string s, find the longest palindromic subsequence's length in s. You may assume that the ma ...