最近用wpf做了个项目,安装用户很多,每次功能更新,都要打包后发给用户重新安装。为了避免麻烦,要实现远程更新势在必行。
网上找了很多资料,有说用框架,有说自己实现。最终还是自己写吧,
实现逻辑:
1、主程序调用服务获取版本号比较,需求更新启动更新程序,杀死主程序进程。
2、更新程序调用服务下载更新文件为zip压缩文件。下载完毕后解压缩,复制到主程序目前完成文件替换。
3、启动主程序,杀死更新程序进程。
技术点:服务端使用netcore2.0 webapi 部署到Docker容器。
解压缩使用ICSharpCode.SharpZipLib。NUGET可下载。
更新程序关键代码:
public MainWindow()
{
InitializeComponent();
updateUrl= ConfigurationManager.AppSettings["updateUrl"];
this.Label.Content = msg;
this.StartTask();
}private async void StartTask()
{
try
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\\Fosafer\\Update";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}this.Label.Content = "正在下载更新文件...";
var filepath = await DownFile(path);
this.Label.Content = "文件下载完成!";
await Task.Delay(500);
if (File.Exists(filepath))
{
this.Label.Content = "正在解压安装包...";
var result = await UnZip(filepath);
this.Label.Content = "文件下载完成!";
await Task.Delay(500);
if (result)
{
this.Label.Content = "正在更新文件...";var update = await UpdateFile(path+"\\uap_client_install");
if (update)
{
this.Label.Content = "客户端更新成功!";
Directory.Delete(path,true);
}
}
else
{
this.Label.Content = "文件解压异常...";
}
}
else
{
this.Label.Content = "文件更新失败,联系管理员...";
}
await Task.Delay(500);
this.Label.Content = "启动客户端";
var process = Process.Start(AppDomain.CurrentDomain.BaseDirectory+ "客户端.exe");
}
catch (Exception e)
{
Console.WriteLine(e);
}
await Task.Delay(500);
Environment.Exit(0);}
private Task<string> DownFile(string filePath)
{
string url = updateUrl + "/api/v1/Version/Download";
return DownLoadFile(url, filePath);
}private Task<bool> UnZip(string filePath)
{
return Task<bool>.Factory.StartNew(() => ZipLibHelper.DecomparessFile(filePath));
}private Task<bool> UpdateFile(string filePath)
{
var result = Task<bool>.Factory.StartNew(() =>
{
var files = Directory.GetFiles(filePath);
foreach (var file in files)
{
var fileNames = file.Split('\\');
var fieName = fileNames[fileNames.Length - 1];
var destFile = AppDomain.CurrentDomain.BaseDirectory + fieName;
if (File.Exists(destFile))
{
File.Delete(destFile);
}
File.Copy(file,destFile);
}
return true;
});
return result;
}/// <summary>
/// Downs the load file.
/// </summary>
/// <param name="url">api地址</param>
/// <param name="savePath">文件保存路径</param>
/// <returns></returns>
public async Task<string> DownLoadFile(string url, string savePath)
{
string newFileName = savePath + "\\install.zip";
using (HttpClient httpClient = new HttpClient())
{
try
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = httpClient.GetAsync(url).Result;
if (response.IsSuccessStatusCode)
{
var ms = await response.Content.ReadAsStreamAsync();
using (var br = new BinaryReader(ms))
{
var data = br.ReadBytes((int)ms.Length);
File.WriteAllBytes(newFileName, data);}
}
}
catch (Exception e)
{
logger.Info($"http get error,url={url},exception:{e}");
}
}
return newFileName;
}
主程序调用代码:
private void CheckVersion()
{
Log.Logger.Instance.Log($"开始版本检测", Category.Debug);
var versionNo = ServiceManageHelp.Instance.GetVersion();
if (string.IsNullOrEmpty(versionNo))
{
return;
}
var localVersion = int.Parse(ConfigData.VersionNo.Replace(".", ""));
Log.Logger.Instance.Log($"服务端版本号:{versionNo}", Category.Debug);
if (localVersion < int.Parse(versionNo))
{
Current.Dispatcher?.Invoke(new System.Action(delegate
{
if (UCP.Controls.MessageBox.Show("发现新版本,是否下载更新?", "系统提示", MessageBoxButton.OKCancel) ==
MessageBoxResult.OK)
{
OpenUpdateApp();
}
}));}
}
private void OpenUpdateApp()
{
var process = Process.Start(AppDomain.CurrentDomain.BaseDirectory + "Update.exe");
Environment.Exit(0);
}
完整代码:https://download.csdn.net/download/esiangchioa/11579921