feat.初步完成自动更新功能

This commit is contained in:
MistEO
2021-09-27 00:11:41 +08:00
parent 2e57eb1618
commit 7b1441fa6c
5 changed files with 261 additions and 55 deletions

View File

@@ -1,4 +1,7 @@
using System.Windows;
using Microsoft.Toolkit.Uwp.Notifications;
using System.Windows;
using Windows.ApplicationModel.Activation;
using Windows.UI.Notifications;
namespace MeoAsstGui
{
@@ -7,5 +10,25 @@ namespace MeoAsstGui
/// </summary>
public partial class App : Application
{
//protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
//{
// var deferral = args.TaskInstance.GetDeferral();
// switch (args.TaskInstance.Task.Name)
// {
// case "ToastBackgroundTask":
// var details = args.TaskInstance.TriggerDetails as ToastNotificationActionTriggerDetail;
// if (details != null)
// {
// ToastArguments arguments = ToastArguments.Parse(details.Argument);
// var userInput = details.UserInput;
// // Perform tasks
// }
// break;
// }
// deferral.Complete();
//}
}
}

View File

@@ -17,9 +17,10 @@ namespace MeoAsstGui
protected override void OnViewLoaded()
{
CheckAndUpdateNow();
InitProxy();
CheckUpdate();
InitViewModels();
ShowUpdateOrDownload();
}
private void InitProxy()
@@ -37,20 +38,27 @@ namespace MeoAsstGui
Items.Add(rvm);
ActiveItem = mfvm;
}
private async void CheckUpdate()
private bool CheckAndUpdateNow()
{
var vuvm = _container.Get<VersionUpdateViewModel>();
return vuvm.CheckAndUpdateNow();
}
private async void ShowUpdateOrDownload()
{
var vuvm = _container.Get<VersionUpdateViewModel>();
var task = Task.Run(() =>
{
return vuvm.CheckUpdate();
});
var needUpdate = await task;
if (needUpdate)
{
_windowManager.ShowWindow(vuvm);
if (vuvm.IsFirstBootAfterUpdate)
{
_windowManager.ShowWindow(vuvm);
}
else
{
var task = Task.Run(() =>
{
return vuvm.CheckAndDownloadUpdate();
});
await task;
}
}
}

View File

@@ -1,12 +1,15 @@
using Newtonsoft.Json;
using Microsoft.Toolkit.Uwp.Notifications;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Stylet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
namespace MeoAsstGui
{
public class VersionUpdateViewModel : Screen
@@ -23,7 +26,7 @@ namespace MeoAsstGui
private string _curVersion = Marshal.PtrToStringAnsi(AsstGetVersion());
private string _latestVersion;
private string _updateTag;
private string _updateTag = ViewStatusStorage.Get("VersionUpdate.name", string.Empty);
public string UpdateTag
{
get
@@ -33,10 +36,11 @@ namespace MeoAsstGui
set
{
SetAndNotify(ref _updateTag, value);
ViewStatusStorage.Set("VersionUpdate.name", value);
}
}
private string _updateInfo;
private string _updateInfo = ViewStatusStorage.Get("VersionUpdate.body", string.Empty);
public string UpdateInfo
{
@@ -47,16 +51,176 @@ namespace MeoAsstGui
set
{
SetAndNotify(ref _updateInfo, value);
ViewStatusStorage.Set("VersionUpdate.body", value);
}
}
private string RequestApi()
}
private bool _isFirstBootAfterUpdate = Convert.ToBoolean(ViewStatusStorage.Get("VersionUpdate.firstboot", Boolean.FalseString));
public bool IsFirstBootAfterUpdate
{
HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(
"https://api.github.com/repos/MistEO/MeoAssistance/releases/latest");
get
{
return _isFirstBootAfterUpdate;
}
set
{
SetAndNotify(ref _isFirstBootAfterUpdate, value);
ViewStatusStorage.Set("VersionUpdate.firstboot", value.ToString());
}
}
private const string _requestUrl = "https://api.github.com/repos/MistEO/MeoAssistance/releases/latest";
private JObject _lastestJson;
private string _downloadUrl;
string _extractDir = Directory.GetCurrentDirectory() + "\\NewVersion";
// 检查是否有已下载的更新包,如果有立即更新并重启进程
public bool CheckAndUpdateNow()
{
if (UpdateTag == string.Empty || !Directory.Exists(_extractDir))
{
return false;
}
var uncopiedList = new List<string>();
// 复制新版本的所有文件到当前路径下
foreach (var file in Directory.GetFiles(_extractDir))
{
try
{
File.Copy(file, Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileName(file)), true);
}
catch (Exception)
{
uncopiedList.Add(file);
}
}
foreach (var directory in Directory.GetDirectories(_extractDir))
{
CopyFilesRecursively(directory, Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileName(directory)));
}
// 程序正在运行中,部分文件是无法覆写的,这里曲线操作下
// 先将当前这些文件重命名,然后再把新的复制过来
foreach (var oldfile in Directory.GetFiles(Directory.GetCurrentDirectory(), "*.old"))
{
File.Delete(oldfile);
}
foreach (var file in uncopiedList)
{
string curFileName = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileName(file));
File.Move(curFileName, curFileName + ".old");
File.Copy(file, curFileName);
}
// 操作完了,把更新包里的文件删了
Directory.Delete(_extractDir, true);
// 保存更新信息,下次启动后会弹出已更新完成的提示
IsFirstBootAfterUpdate = true;
ViewStatusStorage.Save();
// 重启进程(启动的是更新后的程序了)
System.Diagnostics.Process newProcess = new System.Diagnostics.Process();
newProcess.StartInfo.FileName = System.AppDomain.CurrentDomain.FriendlyName;
newProcess.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
newProcess.Start();
Application.Current.Shutdown();
return true;
}
// 检查更新,并下载更新包
public bool CheckAndDownloadUpdate()
{
// 检查更新
if (!CheckUpdate())
{
return false;
}
var openUrlToastButton = new ToastButton();
openUrlToastButton.SetContent("前往页面查看");
new ToastContentBuilder()
.AddText("检测到新版本:" + _lastestJson["name"].ToString() + ",正在后台下载……")
.AddText(_lastestJson["body"].ToString())
.AddButton(openUrlToastButton)
.Show();
// 下载压缩包
const int downloadRetryMaxTimes = 20;
string downloadFilename = _downloadUrl.Substring(_downloadUrl.LastIndexOf('/') + 1);
string downloadTempFilename = downloadFilename + ".tmp";
bool downloaded = false;
for (int i = 0; i != downloadRetryMaxTimes; ++i)
{
if (DownloadFile(_downloadUrl, downloadTempFilename))
{
downloaded = true;
break;
}
}
if (!downloaded)
{
new ToastContentBuilder()
.AddText("新版本下载失败请尝试手动下载_(:з」∠)_")
.AddButton(openUrlToastButton)
.Show();
return false;
}
// 解压并删除压缩包
File.Copy(downloadTempFilename, downloadFilename, true);
File.Delete(downloadTempFilename);
System.IO.Compression.ZipFile.ExtractToDirectory(downloadFilename, _extractDir);
File.Delete(downloadFilename);
// 把相关信息存下来,更新完之后启动的时候显示
UpdateTag = "版本已自动更新:" + _lastestJson["name"].ToString();
UpdateInfo = _lastestJson["body"].ToString();
new ToastContentBuilder()
.AddText("新版本下载完成,将在下次启动辅助时自动更新!✿✿ヽ(°▽°)ノ✿")
.Show();
return true;
}
public bool CheckUpdate()
{
string response = string.Empty;
const int requestRetryMaxTimes = 20;
for (int i = 0; i != requestRetryMaxTimes; ++i)
{
response = RequestApi(_requestUrl);
if (response.Length != 0)
{
break;
}
}
if (response.Length == 0)
{
return false;
}
JObject json = (JObject)JsonConvert.DeserializeObject(response);
_latestVersion = json["tag_name"].ToString();
if (string.Compare(_latestVersion, _curVersion) <= 0
|| ViewStatusStorage.Get("VersionUpdate.Ignore", string.Empty) == _latestVersion)
{
return false;
}
foreach (JObject asset in json["assets"])
{
string downUrl = asset["browser_download_url"].ToString();
if (downUrl.IndexOf("MeoAssistance") != -1)
{
_downloadUrl = downUrl;
_lastestJson = json;
return true;
}
}
return false;
}
private string RequestApi(string url)
{
HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
httpWebRequest.Method = "GET";
httpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36";
httpWebRequest.Accept = "application/vnd.github.v3+json";
httpWebRequest.Timeout = 20000;
//httpWebRequest.Timeout = 20000;
try
{
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
@@ -71,47 +235,57 @@ namespace MeoAsstGui
return string.Empty;
}
}
private string _latestUrl = "https://github.com/MistEO/MeoAssistance/releases/latest";
public bool CheckUpdate()
private bool DownloadFile(string url, string path)
{
string response = RequestApi();
if (response.Length == 0)
HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
httpWebRequest.Method = "GET";
httpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36";
httpWebRequest.Accept = "application/vnd.github.v3+json";
httpWebRequest.Timeout = 20 * 1000;
try
{
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
Stream reponseStream = httpWebResponse.GetResponseStream();
Stream fileStream = new FileStream(path, FileMode.Create);
byte[] bArr = new byte[4096];
int size = reponseStream.Read(bArr, 0, (int)bArr.Length);
while (size > 0)
{
fileStream.Write(bArr, 0, size);
size = reponseStream.Read(bArr, 0, (int)bArr.Length);
};
fileStream.Close();
reponseStream.Close();
httpWebResponse.Close();
return true;
}
catch (Exception)
{
return false;
}
JObject json = (JObject)JsonConvert.DeserializeObject(response);
_latestVersion = json["tag_name"].ToString();
if (string.Compare(_latestVersion, _curVersion) <= 0
|| ViewStatusStorage.Get("VersionUpdate.Ignore", string.Empty) == _latestVersion)
{
return false;
}
UpdateTag = "新版本:" + json["name"].ToString();
UpdateInfo = json["body"].ToString();
_latestUrl = json["html_url"].ToString();
return true;
}
public void Download()
{
System.Diagnostics.Process.Start(_latestUrl);
RequestClose();
private static void CopyFilesRecursively(string sourcePath, string targetPath)
{
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath));
}
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
{
File.Copy(newPath, newPath.Replace(sourcePath, targetPath), true);
}
}
public void Close()
{
RequestClose();
}
public void Ignore()
{
ViewStatusStorage.Set("VersionUpdate.Ignore", _latestVersion);
RequestClose();
IsFirstBootAfterUpdate = false;
UpdateTag = "";
UpdateInfo = "";
}
}
}

View File

@@ -5,7 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
Title="有新版本" Height="500" Width="600">
Title="版本已自动更新" Height="500" Width="600">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80" />
@@ -21,9 +21,9 @@
</ScrollViewer>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Grid.Row="2">
<Button Command="{s:Action Download}" Content="前往下载" Margin="20" Width="120" Height="60" />
<!--<Button Command="{s:Action Download}" Content="前往下载" Margin="20" Width="120" Height="60" />-->
<!--<Button Command="{s:Action Ignore}" Content="不再提示" Margin="20" Width="120" Height="60" />-->
<Button Command="{s:Action Close}" Content="下次一定" Margin="20" Width="120" Height="60" />
<Button Command="{s:Action Close}" Content="好的!" Margin="20" Width="120" Height="60" />
</StackPanel>
</Grid>
</Window>

View File

@@ -8,6 +8,7 @@
<package id="NETStandard.Library" version="2.0.3" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
<package id="Stylet" version="1.3.6" targetFramework="net472" />
<package id="Microsoft.Toolkit.Uwp.Notifications" version="7.1.0" targetFramework="net472" />
<package id="System.AppContext" version="4.3.0" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.Collections" version="4.3.0" targetFramework="net472" />