diff --git a/YaeAchievement.csproj b/YaeAchievement.csproj index 4a61f4c..cf102bd 100644 --- a/YaeAchievement.csproj +++ b/YaeAchievement.csproj @@ -30,6 +30,10 @@ ResXFileCodeGenerator App.Designer.cs + + + PreserveNewest + diff --git a/res/App.Designer.cs b/res/App.Designer.cs index 3822fbf..b5000ca 100644 --- a/res/App.Designer.cs +++ b/res/App.Designer.cs @@ -18,7 +18,7 @@ namespace YaeAchievement.res { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class App { @@ -301,15 +301,6 @@ namespace YaeAchievement.res { } } - /// - /// Looks up a localized string similar to Unzip the package to update application.. - /// - internal static string UpdateDownloadFinish { - get { - return ResourceManager.GetString("UpdateDownloadFinish", resourceCulture); - } - } - /// /// Looks up a localized string similar to Downloading update package.... /// @@ -328,6 +319,16 @@ namespace YaeAchievement.res { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] Updater { + get { + object obj = ResourceManager.GetObject("Updater", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized string similar to Upload error to appcenter.... /// diff --git a/res/App.resx b/res/App.resx index e8f2e59..731dd16 100644 --- a/res/App.resx +++ b/res/App.resx @@ -101,9 +101,6 @@ Input a number (0-5): Downloading update package... - - Unzip the package to update application. - YaeAchievement ({0}) @@ -125,4 +122,8 @@ Input a number (0-5): Network error ({0}: {1}) + + + Updater.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/res/App.zh.resx b/res/App.zh.resx index dff31f0..1cf073c 100644 --- a/res/App.zh.resx +++ b/res/App.zh.resx @@ -95,9 +95,6 @@ 正在下载更新包... - - 关闭程序后, 将压缩包解压至当前目录即可完成更新. - YaeAchievement - 原神成就导出工具 ({0}) diff --git a/res/Updater.exe b/res/Updater.exe new file mode 100644 index 0000000..ea97c8a Binary files /dev/null and b/res/Updater.exe differ diff --git a/src/Export.cs b/src/Export.cs index 4eb9053..6f7442f 100644 --- a/src/Export.cs +++ b/src/Export.cs @@ -44,7 +44,7 @@ public static class Export { RequestUri = new Uri($"https://77.cocogoat.work/v1/memo?source={App.AllAchievement}"), Content = new StringContent(result, Encoding.UTF8, "application/json") }; - using var response = Utils.CHttpClient.Value.Send(request); + using var response = Utils.CHttpClient.Send(request); if (response.StatusCode != HttpStatusCode.Created) { Console.WriteLine(App.ExportToCocogoatFail); return; @@ -60,14 +60,14 @@ public static class Export { var id = Guid.NewGuid().ToString("N").Substring(20, 8); var result = JsonSerializer.Serialize(new Dictionary { { "key", id }, - { "data", data.List.Where(a => a.Status is Status.Finished or Status.RewardTaken) } + { "data", ExportToUIAFApp(data) } }); using var request = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri("https://api.qyinter.com/achievementRedis"), Content = new StringContent(result, Encoding.UTF8, "application/json") }; - using var response = Utils.CHttpClient.Value.Send(request); + using var response = Utils.CHttpClient.Send(request); Console.WriteLine(App.ExportToWxApp1Success, id); } diff --git a/src/Utils.cs b/src/Utils.cs index e48b6d7..4873b89 100644 --- a/src/Utils.cs +++ b/src/Utils.cs @@ -14,19 +14,16 @@ namespace YaeAchievement; public static class Utils { - public static readonly Lazy CHttpClient = new (() => { - var c = new HttpClient(new HttpClientHandler { - Proxy = GlobalVars.DebugProxy ? new WebProxy("http://127.0.0.1:8888") : null, - AutomaticDecompression = DecompressionMethods.Brotli | DecompressionMethods.GZip - }) { - DefaultRequestHeaders = { - UserAgent = { - new ProductInfoHeaderValue("YaeAchievement", GlobalVars.AppVersion.ToString(2)) - } + public static readonly HttpClient CHttpClient = new (new HttpClientHandler { + Proxy = GlobalVars.DebugProxy ? new WebProxy("http://127.0.0.1:8888") : null, + AutomaticDecompression = DecompressionMethods.Brotli | DecompressionMethods.GZip + }) { + DefaultRequestHeaders = { + UserAgent = { + new ProductInfoHeaderValue("YaeAchievement", GlobalVars.AppVersion.ToString(2)) } - }; - return c; - }); + } + }; public static byte[] GetBucketFileAsByteArray(string path, bool cache = true) { try { @@ -38,7 +35,7 @@ public static class Utils { if (cache && cacheFile.Exists()) { msg.Headers.TryAddWithoutValidation("If-None-Match", $"{cacheFile.Read().Etag}"); } - using var response = CHttpClient.Value.Send(msg); + using var response = CHttpClient.Send(msg); if (cache && response.StatusCode == HttpStatusCode.NotModified) { return cacheFile.Read().Content.ToByteArray(); } @@ -90,10 +87,16 @@ public static class Utils { Console.WriteLine(App.UpdateDescription, info.Description); if (info.EnableAutoDownload) { Console.WriteLine(App.UpdateDownloading); - var fullPath = Path.GetFullPath($"update.{Path.GetExtension(info.PackageLink)}"); - File.WriteAllBytes(fullPath, GetBucketFileAsByteArray(info.PackageLink)); - Console.WriteLine(App.UpdateDownloadFinish); - ShellOpen(fullPath); + var tmpPath = Path.GetTempFileName(); + File.WriteAllBytes(tmpPath, GetBucketFileAsByteArray(info.PackageLink)); + var updaterArgs = $"{Environment.ProcessId}|{Environment.ProcessPath}|{tmpPath}"; + var updaterPath = Path.Combine(GlobalVars.DataPath, "update.exe"); + var updaterHash = App.Updater.MD5Hash(); + if (!File.Exists(updaterPath) || File.ReadAllBytes(updaterPath).MD5Hash() != updaterHash) { + File.WriteAllBytes(updaterPath, App.Updater); + } + ShellOpen(updaterPath, updaterArgs.ToBytes().ToBase64()); + GlobalVars.PauseOnExit = false; Environment.Exit(0); } Console.WriteLine(App.DownloadLink, info.PackageLink); @@ -109,7 +112,6 @@ public static class Utils { } } - public static void CheckSelfIsRunning() { Process.EnterDebugMode(); var cur = Process.GetCurrentProcess(); @@ -123,13 +125,17 @@ public static class Utils { } // ReSharper disable once UnusedMethodReturnValue.Global - public static bool ShellOpen(string path) { + public static bool ShellOpen(string path, string? args = null) { try { + var startInfo = new ProcessStartInfo { + FileName = path, + UseShellExecute = true + }; + if (args != null) { + startInfo.Arguments = args; + } return new Process { - StartInfo = { - FileName = path, - UseShellExecute = true - } + StartInfo = startInfo }.Start(); } catch (Exception) { return false; @@ -162,8 +168,10 @@ public static class Utils { public static void InstallExitHook() { AppDomain.CurrentDomain.ProcessExit += (_, _) => { proc?.Kill(); - Console.WriteLine(App.PressKeyToExit); - Console.ReadKey(); + if (GlobalVars.PauseOnExit) { + Console.WriteLine(App.PressKeyToExit); + Console.ReadKey(); + } }; } @@ -258,11 +266,8 @@ public static class Utils { if (!installed) { Console.WriteLine(App.VcRuntimeDownload); var pkgPath = Path.Combine(GlobalVars.DataPath, "vc_redist.x64.exe"); - var stream = await CHttpClient.Value.GetStreamAsync("https://aka.ms/vs/17/release/vc_redist.x64.exe"); - var output = File.OpenWrite(pkgPath); - await stream.CopyToAsync(output); - stream.Close(); - output.Close(); + var bytes = await CHttpClient.GetByteArrayAsync("https://aka.ms/vs/17/release/vc_redist.x64.exe"); + await File.WriteAllBytesAsync(pkgPath, bytes); Console.WriteLine(App.VcRuntimeInstalling); using var process = new Process { StartInfo = {