From e6c91e12c8a6ae3fb8030d0e0736f7d35f0aa9f1 Mon Sep 17 00:00:00 2001 From: Slnanx Date: Sun, 17 Nov 2024 15:18:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=B8=BASystem.Text.Json:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- v2rayN/AmazTool/AmazTool.csproj | 11 +- v2rayN/AmazTool/LocalizationHelper.cs | 194 ++++++++++---------------- v2rayN/AmazTool/Program.cs | 41 +++++- v2rayN/AmazTool/UpgradeApp.cs | 147 +++++++++++++------ v2rayN/AmazTool/en-US.json | 14 ++ v2rayN/AmazTool/zh-CN.json | 14 ++ 6 files changed, 250 insertions(+), 171 deletions(-) create mode 100644 v2rayN/AmazTool/en-US.json create mode 100644 v2rayN/AmazTool/zh-CN.json diff --git a/v2rayN/AmazTool/AmazTool.csproj b/v2rayN/AmazTool/AmazTool.csproj index 37193d62..7982f54f 100644 --- a/v2rayN/AmazTool/AmazTool.csproj +++ b/v2rayN/AmazTool/AmazTool.csproj @@ -3,10 +3,17 @@ Exe net8.0 + true + true + win-x64 enable enable - Copyright © 2017-2024 (GPLv3) - 1.3.0 + Copyright © 2017-2024 (GPLv3) + 1.3.0 + + + + \ No newline at end of file diff --git a/v2rayN/AmazTool/LocalizationHelper.cs b/v2rayN/AmazTool/LocalizationHelper.cs index 116fe465..eb6d4fe0 100644 --- a/v2rayN/AmazTool/LocalizationHelper.cs +++ b/v2rayN/AmazTool/LocalizationHelper.cs @@ -1,131 +1,83 @@ -using System.Collections.Generic; +/** + * 该程序使用JSON文件对C#应用程序进行本地化。 + * 程序根据系统当前的语言加载相应的语言文件。 + * 如果当前语言不被支持,则默认使用英语。 + * + * 库: + * - System.Collections.Generic + * - System.Globalization + * - System.IO + * - System.Text.Json + * + * 用法: + * - 为每种支持的语言创建JSON文件(例如,en.json,zh.json)。 + * - 将JSON文件放置程序同目录中。 + * - 运行程序,它将根据系统当前的语言加载翻译。 + * - 调用方式: localization.Translate("Try_Terminate_Process") //返回一个 string 字符串 + * 示例JSON文件(en.json): + * { + * "Restart_v2rayN": "Start v2rayN, please wait...", + * "Guidelines": "Please run it from the main application." + * } + * + * 示例JSON文件(zh.json): + * { + * "Restart_v2rayN": "正在重启,请等待...", + * "Guidelines": "请从主应用运行!" + * } + */ + +using System; +using System.Collections.Generic; using System.Globalization; +using System.IO; +using System.Text.Json; -namespace AmazTool +public class Localization { - public class LocalizationHelper + private Dictionary translations; + + public Localization() { - /// - /// 获取系统当前语言的本地化字符串 - /// - /// 要翻译的关键字 - /// 对应语言的本地化字符串,如果没有找到则返回关键字 - public static string GetLocalizedValue(string key) + // 获取当前系统的完整文化名称 例:zh-CN en-US + string currentLanguage = CultureInfo.CurrentCulture.Name; + + // 如果当前语言不是"zh-CN"或"en-US",默认使用英文 + if (currentLanguage != "zh-CN" && currentLanguage != "en-US") { - // 定义支持的语言 - HashSet supportedLanguages = ["zh", "en"]; - - // 获取当前系统语言的 ISO 两字母代码 - string currentLanguage = CultureInfo.CurrentCulture.TwoLetterISOLanguageName; - - // 如果当前语言不在支持的语言列表中,默认使用英文 - if (!supportedLanguages.Contains(currentLanguage)) - { - currentLanguage = "en"; - } - - // 尝试获取对应语言的翻译 - if (languageResources.TryGetValue(key, out var translations)) - { - if (translations.TryGetValue(currentLanguage, out var translation)) - { - return translation; - } - } - - // 如果未找到翻译,返回关键字本身 - return key; + currentLanguage = "en-US"; } - /// - /// 存储不同语言的本地化资源 - /// - public static Dictionary> languageResources = new() + // 加载相应语言的JSON文件 + string jsonFilePath = $"{currentLanguage}.json"; + if (!LoadTranslations(jsonFilePath)) { - { - "Guidelines", new Dictionary - { - { "en", "Please run it from the main application." }, - { "zh", "请从主应用运行!" } - } - }, - { - "Upgrade_File_Not_Found", new Dictionary - { - { "en", "Upgrade failed, file not found." }, - { "zh", "升级失败,文件不存在!" } - } - }, - { - "In_Progress", new Dictionary - { - { "en", "In progress, please wait..." }, - { "zh", "正在进行中,请等待..." } - } - }, - { - "Try_Terminate_Process", new Dictionary - { - { "en", "Try to terminate the v2rayN process." }, - { "zh", "尝试结束 v2rayN 进程..." } - } - }, - { - "Failed_Terminate_Process", new Dictionary - { - { "en", "Failed to terminate the v2rayN.Close it manually,or the upgrade may fail." }, - { "zh", "请手动关闭正在运行的v2rayN,否则可能升级失败。" } - } - }, - { - "Start_Unzipping", new Dictionary - { - { "en", "Start extracting the update package." }, - { "zh", "开始解压缩更新包..." } - } - }, - { - "Success_Unzipping", new Dictionary - { - { "en", "Successfully extracted the update package!" }, - { "zh", "解压缩更新包成功!" } - } - }, - { - "Failed_Unzipping", new Dictionary - { - { "en", "Failed to extract the update package!" }, - { "zh", "解压缩更新包失败!" } - } - }, - { - "Failed_Upgrade", new Dictionary - { - { "en", "Upgrade failed!" }, - { "zh", "升级失败!" } - } - }, - { - "Success_Upgrade", new Dictionary - { - { "en", "Upgrade success!" }, - { "zh", "升级成功!" } - } - }, - { - "Information", new Dictionary - { - { "en", "Information" }, - { "zh", "提示" } - } - }, - { - "Restart_v2rayN", new Dictionary - { - { "en", "Start v2rayN, please wait..." }, - { "zh", "正在重启,请等待..." } - } - } - }; + // 如果加载失败,则使用默认语言 + jsonFilePath = "en-US.json"; + LoadTranslations(jsonFilePath); + } + } + + private bool LoadTranslations(string jsonFilePath) + { + try + { + // 读取JSON文件内容 + var json = File.ReadAllText(jsonFilePath); + // 解析JSON内容 + translations = JsonSerializer.Deserialize>(json); + return true; // 成功读取和解析JSON文件 + } + catch (Exception ex) + { + Console.WriteLine($"Failed to load JSON file: {ex.Message}"); + Environment.Exit(1); + return false; // 读取或解析JSON文件失败 + } + } + + public string Translate(string key) + { + return translations != null && translations.TryGetValue(key, out string value) ? value : key; } } diff --git a/v2rayN/AmazTool/Program.cs b/v2rayN/AmazTool/Program.cs index 74725033..a5527486 100644 --- a/v2rayN/AmazTool/Program.cs +++ b/v2rayN/AmazTool/Program.cs @@ -1,4 +1,34 @@ -using System; +/** + * 该程序使用JSON文件对C#应用程序进行本地化。 + * 程序根据系统当前的语言加载相应的语言文件。 + * 如果当前语言不被支持,则默认使用英语。 + * + * 库: + * - System + * - System.Threading + * + * 用法: + * - 为每种支持的语言创建JSON文件(例如,en.json,zh.json)。 + * - 将JSON文件放置程序同目录中。 + * - 运行程序,它将根据系统当前的语言加载翻译。 + * - 调用方式: localization.Translate("Try_Terminate_Process") //返回一个 string 字符串 + * 示例JSON文件(en.json): + * { + * "Restart_v2rayN": "Start v2rayN, please wait...", + * "Guidelines": "Please run it from the main application." + * } + * + * 示例JSON文件(zh.json): + * { + * "Restart_v2rayN": "正在重启,请等待...", + * "Guidelines": "请从主应用运行!" + * } + * + * 注意: + * - 确保通过NuGet安装了Newtonsoft.Json库。 + */ + +using System; using System.Threading; namespace AmazTool @@ -11,15 +41,20 @@ namespace AmazTool [STAThread] private static void Main(string[] args) { + var localization = new Localization(); + if (args.Length == 0) { - Console.WriteLine(LocalizationHelper.GetLocalizedValue("Guidelines")); + // 不能直接打开更新程序 + Console.WriteLine(localization.Translate("Guidelines")); Thread.Sleep(5000); return; } + // 解析并拼接命令行参数以获取文件名 var fileName = Uri.UnescapeDataString(string.Join(" ", args)); + // 调用升级方法进行文件处理 UpgradeApp.Upgrade(fileName); } } -} \ No newline at end of file +} diff --git a/v2rayN/AmazTool/UpgradeApp.cs b/v2rayN/AmazTool/UpgradeApp.cs index afab6cba..8f125149 100644 --- a/v2rayN/AmazTool/UpgradeApp.cs +++ b/v2rayN/AmazTool/UpgradeApp.cs @@ -1,4 +1,37 @@ -using System; +/** + * 该程序使用JSON文件对C#应用程序进行本地化。 + * 程序根据系统当前的语言加载相应的语言文件。 + * 如果当前语言不被支持,则默认使用英语。 + * + * 库: + * - System + * - System.Collections.Generic + * - System.Globalization + * - System.IO + * - Newtonsoft.Json + * + * 用法: + * - 为每种支持的语言创建JSON文件(例如,en.json,zh.json)。 + * - 将JSON文件放置程序同目录中。 + * - 运行程序,它将根据系统当前的语言加载翻译。 + * - 调用方式: localization.Translate("Try_Terminate_Process") //返回一个 string 字符串 + * 示例JSON文件(en.json): + * { + * "Restart_v2rayN": "Start v2rayN, please wait...", + * "Guidelines": "Please run it from the main application." + * } + * + * 示例JSON文件(zh.json): + * { + * "Restart_v2rayN": "正在重启,请等待...", + * "Guidelines": "请从主应用运行!" + * } + * + * 注意: + * - 确保通过NuGet安装了Newtonsoft.Json库。 + */ + +using System; using System.Diagnostics; using System.IO; using System.IO.Compression; @@ -9,41 +42,64 @@ namespace AmazTool { internal class UpgradeApp { + // 定义常量 + private static readonly string V2rayN = "v2rayN"; + private static readonly string SplitKey = "/"; + public static void Upgrade(string fileName) { - Console.WriteLine(fileName); + var localization = new Localization(); + Console.WriteLine(fileName); Thread.Sleep(9000); if (!File.Exists(fileName)) { - Console.WriteLine(LocalizationHelper.GetLocalizedValue("Upgrade_File_Not_Found")); + // 如果文件不存在,输出相应的本地化信息 + Console.WriteLine(localization.Translate("Upgrade_File_Not_Found")); return; } - Console.WriteLine(LocalizationHelper.GetLocalizedValue("Try_Terminate_Process")); + // 尝试终止进程 + TerminateProcess(localization); + + // 解压缩更新包 + ExtractUpdatePackage(fileName, localization); + + // 重启进程 + Console.WriteLine(localization.Translate("Restart_v2rayN")); + Thread.Sleep(9000); + RestartProcess(); + } + + private static void TerminateProcess(Localization localization) + { + Console.WriteLine(localization.Translate("Try_Terminate_Process")); try { - var existing = Process.GetProcessesByName(V2rayN); - foreach (var pp in existing) + var processes = Process.GetProcessesByName(V2rayN); + foreach (var process in processes) { - pp?.Kill(); - pp?.WaitForExit(1000); + process?.Kill(); + process?.WaitForExit(1000); } } catch (Exception ex) { - // Access may be denied without admin right. The user may not be an administrator. - Console.WriteLine(LocalizationHelper.GetLocalizedValue("Failed_Terminate_Process") + ex.StackTrace); + // 如果无法终止进程,输出相应的本地化信息和错误堆栈 + Console.WriteLine(localization.Translate("Failed_Terminate_Process") + ex.StackTrace); } + } + + private static void ExtractUpdatePackage(string fileName, Localization localization) + { + Console.WriteLine(localization.Translate("Start_Unzipping")); + StringBuilder errorLog = new(); - Console.WriteLine(LocalizationHelper.GetLocalizedValue("Start_Unzipping")); - StringBuilder sb = new(); try { - string thisAppOldFile = $"{GetExePath()}.tmp"; - File.Delete(thisAppOldFile); - string splitKey = "/"; + string backupFilePath = $"{GetExePath()}.tmp"; + File.Delete(backupFilePath); using ZipArchive archive = ZipFile.OpenRead(fileName); foreach (ZipArchiveEntry entry in archive.Entries) @@ -51,22 +107,14 @@ namespace AmazTool try { if (entry.Length == 0) - { continue; - } Console.WriteLine(entry.FullName); - var lst = entry.FullName.Split(splitKey); - if (lst.Length == 1) continue; - string fullName = string.Join(splitKey, lst[1..lst.Length]); + string fullPath = GetEntryFullPath(entry.FullName); + BackupExistingFile(fullPath, backupFilePath); - if (string.Equals(GetExePath(), GetPath(fullName), StringComparison.OrdinalIgnoreCase)) - { - File.Move(GetExePath(), thisAppOldFile); - } - - string entryOutputPath = GetPath(fullName); + string entryOutputPath = GetPath(fullPath); Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!); entry.ExtractToFile(entryOutputPath, true); @@ -74,23 +122,39 @@ namespace AmazTool } catch (Exception ex) { - sb.Append(ex.StackTrace); + errorLog.Append(ex.StackTrace); } } } catch (Exception ex) { - Console.WriteLine(LocalizationHelper.GetLocalizedValue("Failed_Upgrade") + ex.StackTrace); - //return; - } - if (sb.Length > 0) - { - Console.WriteLine(LocalizationHelper.GetLocalizedValue("Failed_Upgrade") + sb.ToString()); - //return; + // 如果解压失败,输出相应的本地化信息和错误堆栈 + Console.WriteLine(localization.Translate("Failed_Upgrade") + ex.StackTrace); } - Console.WriteLine(LocalizationHelper.GetLocalizedValue("Restart_v2rayN")); - Thread.Sleep(9000); + if (errorLog.Length > 0) + { + // 如果有任何错误记录,输出相应的本地化信息和错误日志 + Console.WriteLine(localization.Translate("Failed_Upgrade") + errorLog.ToString()); + } + } + + private static void BackupExistingFile(string fullPath, string backupFilePath) + { + if (string.Equals(GetExePath(), fullPath, StringComparison.OrdinalIgnoreCase)) + { + File.Move(GetExePath(), backupFilePath); + } + } + + private static string GetEntryFullPath(string entryName) + { + var parts = entryName.Split(SplitKey); + return parts.Length > 1 ? string.Join(SplitKey, parts[1..]) : entryName; + } + + private static void RestartProcess() + { Process process = new() { StartInfo = new() @@ -115,14 +179,7 @@ namespace AmazTool private static string GetPath(string fileName) { - string startupPath = StartupPath(); - if (string.IsNullOrEmpty(fileName)) - { - return startupPath; - } - return Path.Combine(startupPath, fileName); + return string.IsNullOrEmpty(fileName) ? StartupPath() : Path.Combine(StartupPath(), fileName); } - - private static string V2rayN => "v2rayN"; } -} \ No newline at end of file +} diff --git a/v2rayN/AmazTool/en-US.json b/v2rayN/AmazTool/en-US.json new file mode 100644 index 00000000..f4c0f600 --- /dev/null +++ b/v2rayN/AmazTool/en-US.json @@ -0,0 +1,14 @@ +{ + "Restart_v2rayN": "Start v2rayN, please wait...", + "Guidelines": "Please run it from the main application.", + "Upgrade_File_Not_Found": "Upgrade failed, file not found.", + "In_Progress": "In progress, please wait...", + "Try_Terminate_Process": "Try to terminate the v2rayN process.", + "Failed_Terminate_Process": "Failed to terminate the v2rayN.Close it manually,or the upgrade may fail.", + "Start_Unzipping": "Start extracting the update package.", + "Success_Unzipping": "Successfully extracted the update package!", + "Failed_Unzipping": "Failed to extract the update package!", + "Failed_Upgrade": "Upgrade failed!", + "Success_Upgrade": "Upgrade success!", + "Information": "Information" +} \ No newline at end of file diff --git a/v2rayN/AmazTool/zh-CN.json b/v2rayN/AmazTool/zh-CN.json new file mode 100644 index 00000000..a6b6a1b7 --- /dev/null +++ b/v2rayN/AmazTool/zh-CN.json @@ -0,0 +1,14 @@ +{ + "Restart_v2rayN": "正在重启,请等待...", + "Guidelines": "请从主应用运行!", + "Upgrade_File_Not_Found": "升级失败,文件不存在!", + "In_Progress": "正在进行中,请等待...", + "Try_Terminate_Process": "尝试结束 v2rayN 进程...", + "Failed_Terminate_Process": "请手动关闭正在运行的v2rayN,否则可能升级失败。", + "Start_Unzipping": "开始解压缩更新包...", + "Success_Unzipping": "解压缩更新包成功!", + "Failed_Unzipping": "解压缩更新包失败!", + "Failed_Upgrade": "升级失败!", + "Success_Upgrade": "升级成功!", + "Information": "提示" +} \ No newline at end of file