From 7b12549ce3a9137813d230d316faa4af85e9bed0 Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Tue, 6 Jan 2026 22:38:13 +0800 Subject: [PATCH 01/11] Adapt to .NET 10 New Features --- .../GeneralUpdate.Bowl.csproj | 1 + .../GeneralUpdate.ClientCore.csproj | 1 + .../Internal/Bootstrap/UpdateOption.cs | 6 + .../Shared/Object/Enum/UpdateMode.cs | 7 + .../GeneralUpdate.Core.csproj | 1 + .../GeneralUpdateBootstrap.cs | 318 ++++++++++++++---- .../Strategys/WindowsStrategy.cs | 122 +++---- src/c#/GeneralUpdate.Upgrad/Program.cs | 24 ++ 8 files changed, 346 insertions(+), 134 deletions(-) create mode 100644 src/c#/GeneralUpdate.Common/Shared/Object/Enum/UpdateMode.cs diff --git a/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj b/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj index db1aa75d..c2a62b52 100644 --- a/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj +++ b/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj @@ -65,6 +65,7 @@ + diff --git a/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ClientCore.csproj b/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ClientCore.csproj index c265d3d8..25f13399 100644 --- a/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ClientCore.csproj +++ b/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ClientCore.csproj @@ -63,6 +63,7 @@ + diff --git a/src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs b/src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs index 97675362..b3fc7b0c 100644 --- a/src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs +++ b/src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs @@ -3,6 +3,7 @@ using System.Diagnostics.Contracts; using System.Text; using System.Threading; +using GeneralUpdate.Common.Shared.Object.Enum; namespace GeneralUpdate.Common.Internal.Bootstrap { @@ -47,6 +48,11 @@ private class UpdateOptionPool : ConstantPool /// public static readonly UpdateOption BackUp = ValueOf("BACKUP"); + /// + /// Whether to enable the backup function. + /// + public static readonly UpdateOption Mode = ValueOf("MODE"); + internal UpdateOption(int id, string name) : base(id, name) { } diff --git a/src/c#/GeneralUpdate.Common/Shared/Object/Enum/UpdateMode.cs b/src/c#/GeneralUpdate.Common/Shared/Object/Enum/UpdateMode.cs new file mode 100644 index 00000000..cd05d00a --- /dev/null +++ b/src/c#/GeneralUpdate.Common/Shared/Object/Enum/UpdateMode.cs @@ -0,0 +1,7 @@ +namespace GeneralUpdate.Common.Shared.Object.Enum; + +public enum UpdateMode +{ + Default = 0, + Scripts = 1 +} \ No newline at end of file diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj b/src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj index 69deec57..87f9fec0 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj +++ b/src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj @@ -68,6 +68,7 @@ + diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs index fa53ba0d..bef66f1d 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs +++ b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; +using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Text.Json; @@ -14,30 +16,196 @@ using GeneralUpdate.Common.Internal.Strategy; using GeneralUpdate.Common.Shared; using GeneralUpdate.Common.Shared.Object; +using GeneralUpdate.Common.Shared.Object.Enum; +using GeneralUpdate.Common.Shared.Service; using GeneralUpdate.Core.Strategys; namespace GeneralUpdate.Core { public class GeneralUpdateBootstrap : AbstractBootstrap { - private readonly GlobalConfigInfo _configInfo; + private GlobalConfigInfo _configInfo = new(); private IStrategy? _strategy; + private Func? _customSkipOption; public GeneralUpdateBootstrap() + { + InitializeFromEnvironment(); + } + + #region Launch + + public override async Task LaunchAsync() + { + GeneralTracer.Debug("GeneralUpdateBootstrap Launch."); + StrategyFactory(); + + switch (GetOption(UpdateOption.Mode) ?? UpdateMode.Default) + { + case UpdateMode.Default: + ApplyRuntimeOptions(); + _strategy!.Create(_configInfo); + await DownloadAsync(); + await _strategy.ExecuteAsync(); + break; + + case UpdateMode.Scripts: + await ExecuteWorkflowAsync(); + break; + + default: + throw new ArgumentOutOfRangeException(); + } + + return this; + } + + #endregion + + #region Configuration + + public GeneralUpdateBootstrap SetConfig(Configinfo configInfo) + { + _configInfo = new GlobalConfigInfo + { + MainAppName = configInfo.MainAppName, + InstallPath = configInfo.InstallPath, + ClientVersion = configInfo.ClientVersion, + UpdateLogUrl = configInfo.UpdateLogUrl, + AppSecretKey = configInfo.AppSecretKey, + TempPath = StorageManager.GetTempDirectory("upgrade_temp"), + ReportUrl = configInfo.ReportUrl, + UpdateUrl = configInfo.UpdateUrl, + Scheme = configInfo.Scheme, + Token = configInfo.Token, + DriveEnabled = GetOption(UpdateOption.Drive) ?? false, + PatchEnabled = GetOption(UpdateOption.Patch) ?? true, + Script = configInfo.Script + }; + + InitBlackList(); + return this; + } + + public GeneralUpdateBootstrap SetFieldMappings(Dictionary fieldMappings) + { + _configInfo.FieldMappings = fieldMappings; + return this; + } + + public GeneralUpdateBootstrap SetCustomSkipOption(Func func) + { + Debug.Assert(func != null); + _customSkipOption = func; + return this; + } + + #endregion + + #region Workflow + + private async Task ExecuteWorkflowAsync() + { + try + { + var mainResp = await VersionService.Validate( + _configInfo.UpdateUrl, + _configInfo.ClientVersion, + AppType.ClientApp, + _configInfo.AppSecretKey, + GetPlatform(), + _configInfo.ProductId, + _configInfo.Scheme, + _configInfo.Token); + + _configInfo.IsMainUpdate = CheckUpgrade(mainResp); + + if (CanSkip(CheckForcibly(mainResp.Body))) + return; + + InitBlackList(); + ApplyRuntimeOptions(); + + _configInfo.TempPath = StorageManager.GetTempDirectory("main_temp"); + _configInfo.BackupDirectory = Path.Combine( + _configInfo.InstallPath, + $"{StorageManager.DirectoryName}{_configInfo.ClientVersion}"); + + _configInfo.UpdateVersions = mainResp.Body! + .OrderBy(x => x.ReleaseDate) + .ToList(); + + if (GetOption(UpdateOption.BackUp) ?? true) + { + StorageManager.Backup( + _configInfo.InstallPath, + _configInfo.BackupDirectory, + BlackListManager.Instance.SkipDirectorys); + } + + _strategy!.Create(_configInfo); + + if (_configInfo.IsMainUpdate) + { + await DownloadAsync(); + await _strategy.ExecuteAsync(); + } + else + { + _strategy.StartApp(); + } + } + catch (Exception ex) + { + GeneralTracer.Error( + "The ExecuteWorkflowAsync method in the GeneralUpdateBootstrap class throws an exception.", + ex); + EventManager.Instance.Dispatch(this, new ExceptionEventArgs(ex, ex.Message)); + } + } + + #endregion + + #region Download + + private async Task DownloadAsync() + { + var manager = new DownloadManager( + _configInfo.TempPath, + _configInfo.Format, + _configInfo.DownloadTimeOut); + + manager.MultiAllDownloadCompleted += OnMultiAllDownloadCompleted; + manager.MultiDownloadCompleted += OnMultiDownloadCompleted; + manager.MultiDownloadError += OnMultiDownloadError; + manager.MultiDownloadStatistics += OnMultiDownloadStatistics; + + foreach (var version in _configInfo.UpdateVersions) + manager.Add(new DownloadTask(manager, version)); + + await manager.LaunchTasksAsync(); + } + + #endregion + + #region Helpers + + private void InitializeFromEnvironment() { var json = Environments.GetEnvironmentVariable("ProcessInfo"); - if (string.IsNullOrWhiteSpace(json)) - throw new ArgumentException("json environment variable is not defined"); - - var processInfo = JsonSerializer.Deserialize(json, ProcessInfoJsonContext.Default.ProcessInfo); - if (processInfo == null) - throw new ArgumentException("ProcessInfo object cannot be null!"); - - BlackListManager.Instance?.AddBlackFileFormats(processInfo.BlackFileFormats); - BlackListManager.Instance?.AddBlackFiles(processInfo.BlackFiles); - BlackListManager.Instance?.AddSkipDirectorys(processInfo.SkipDirectorys); - - _configInfo = new() + if (string.IsNullOrWhiteSpace(json)) return; + + var processInfo = JsonSerializer.Deserialize( + json, + ProcessInfoJsonContext.Default.ProcessInfo); + + if (processInfo == null) return; + + BlackListManager.Instance.AddBlackFileFormats(processInfo.BlackFileFormats); + BlackListManager.Instance.AddBlackFiles(processInfo.BlackFiles); + BlackListManager.Instance.AddSkipDirectorys(processInfo.SkipDirectorys); + + _configInfo = new GlobalConfigInfo { MainAppName = processInfo.AppName, InstallPath = processInfo.InstallPath, @@ -60,99 +228,102 @@ public GeneralUpdateBootstrap() }; } - public override async Task LaunchAsync() + private void ApplyRuntimeOptions() { - GeneralTracer.Debug("GeneralUpdateBootstrap Launch."); - StrategyFactory(); - var manager = - new DownloadManager(_configInfo.TempPath, _configInfo.Format, _configInfo.DownloadTimeOut); - manager.MultiAllDownloadCompleted += OnMultiAllDownloadCompleted; - manager.MultiDownloadCompleted += OnMultiDownloadCompleted; - manager.MultiDownloadError += OnMultiDownloadError; - manager.MultiDownloadStatistics += OnMultiDownloadStatistics; - foreach (var versionInfo in _configInfo.UpdateVersions) - { - manager.Add(new DownloadTask(manager, versionInfo)); - } - - await manager.LaunchTasksAsync(); - return this; + _configInfo.Encoding = GetOption(UpdateOption.Encoding) ?? Encoding.Default; + _configInfo.Format = GetOption(UpdateOption.Format) ?? Format.ZIP; + _configInfo.DownloadTimeOut = + GetOption(UpdateOption.DownloadTimeOut) == 0 + ? 60 + : GetOption(UpdateOption.DownloadTimeOut); + _configInfo.DriveEnabled = GetOption(UpdateOption.Drive) ?? false; + _configInfo.PatchEnabled = GetOption(UpdateOption.Patch) ?? true; } - #region public method - - public GeneralUpdateBootstrap SetFieldMappings(Dictionary fieldMappings) + private void InitBlackList() { - _configInfo.FieldMappings = fieldMappings; - return this; + BlackListManager.Instance.AddBlackFiles(_configInfo.BlackFiles); + BlackListManager.Instance.AddBlackFileFormats(_configInfo.BlackFormats); + BlackListManager.Instance.AddSkipDirectorys(_configInfo.SkipDirectorys); } - public GeneralUpdateBootstrap AddListenerMultiAllDownloadCompleted( - Action callbackAction) - => AddListener(callbackAction); - - public GeneralUpdateBootstrap AddListenerMultiDownloadCompleted( - Action callbackAction) - => AddListener(callbackAction); + private bool CanSkip(bool isForcibly) + => !isForcibly && _customSkipOption?.Invoke() == true; - public GeneralUpdateBootstrap AddListenerMultiDownloadError( - Action callbackAction) - => AddListener(callbackAction); + private static bool CheckUpgrade(VersionRespDTO? response) + => response?.Code == 200 && response.Body?.Count > 0; - public GeneralUpdateBootstrap AddListenerMultiDownloadStatistics( - Action callbackAction) - => AddListener(callbackAction); + private static bool CheckForcibly(IEnumerable? versions) + => versions?.Any(v => v.IsForcibly == true) == true; - public GeneralUpdateBootstrap AddListenerException(Action callbackAction) - => AddListener(callbackAction); + private static int GetPlatform() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return PlatformType.Windows; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return PlatformType.Linux; + return -1; + } #endregion - protected override Task ExecuteStrategyAsync()=> throw new NotImplementedException(); - - protected override void ExecuteStrategy() - { - _strategy?.Create(_configInfo); - _strategy?.Execute(); - } + #region Strategy & Events protected override GeneralUpdateBootstrap StrategyFactory() { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - _strategy = new WindowsStrategy(); - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - _strategy = new LinuxStrategy(); - else - throw new PlatformNotSupportedException("The current operating system is not supported!"); + _strategy = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? new WindowsStrategy() + : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) + ? new LinuxStrategy() + : throw new PlatformNotSupportedException("The current operating system is not supported!"); return this; } - - private GeneralUpdateBootstrap AddListener(Action callbackAction) where TArgs : EventArgs + + protected override Task ExecuteStrategyAsync() => throw new NotImplementedException(); + protected override void ExecuteStrategy() => throw new NotImplementedException(); + + private GeneralUpdateBootstrap AddListener(Action action) + where TArgs : EventArgs { - Debug.Assert(callbackAction != null); - EventManager.Instance.AddListener(callbackAction); + EventManager.Instance.AddListener(action); return this; } + public GeneralUpdateBootstrap AddListenerMultiAllDownloadCompleted( + Action cb) => AddListener(cb); + + public GeneralUpdateBootstrap AddListenerMultiDownloadCompleted( + Action cb) => AddListener(cb); + + public GeneralUpdateBootstrap AddListenerMultiDownloadError( + Action cb) => AddListener(cb); + + public GeneralUpdateBootstrap AddListenerMultiDownloadStatistics( + Action cb) => AddListener(cb); + + public GeneralUpdateBootstrap AddListenerException( + Action cb) => AddListener(cb); + private void OnMultiDownloadStatistics(object sender, MultiDownloadStatisticsEventArgs e) { - var message = ObjectTranslator.GetPacketHash(e.Version); - GeneralTracer.Info($"Multi download statistics, {message}[BytesReceived]:{e.BytesReceived} [ProgressPercentage]:{e.ProgressPercentage} [Remaining]:{e.Remaining} [TotalBytesToReceive]:{e.TotalBytesToReceive} [Speed]:{e.Speed}"); + GeneralTracer.Info( + $"Multi download statistics, {ObjectTranslator.GetPacketHash(e.Version)} " + + $"[BytesReceived]:{e.BytesReceived} [ProgressPercentage]:{e.ProgressPercentage} " + + $"[Remaining]:{e.Remaining} [TotalBytesToReceive]:{e.TotalBytesToReceive} [Speed]:{e.Speed}"); EventManager.Instance.Dispatch(sender, e); } private void OnMultiDownloadCompleted(object sender, MultiDownloadCompletedEventArgs e) { - var message = ObjectTranslator.GetPacketHash(e.Version); - GeneralTracer.Info($"Multi download completed, {message}[IsComplated]:{e.IsComplated}."); + GeneralTracer.Info( + $"Multi download completed, {ObjectTranslator.GetPacketHash(e.Version)} [IsCompleted]:{e.IsComplated}"); EventManager.Instance.Dispatch(sender, e); } private void OnMultiDownloadError(object sender, MultiDownloadErrorEventArgs e) { - var message = ObjectTranslator.GetPacketHash(e.Version); - GeneralTracer.Error($"Multi download error {message}.", e.Exception); + GeneralTracer.Error( + $"Multi download error {ObjectTranslator.GetPacketHash(e.Version)}.", + e.Exception); EventManager.Instance.Dispatch(sender, e); } @@ -160,7 +331,8 @@ private void OnMultiAllDownloadCompleted(object sender, MultiAllDownloadComplete { GeneralTracer.Info($"Multi all download completed {e.IsAllDownloadCompleted}."); EventManager.Instance.Dispatch(sender, e); - ExecuteStrategy(); } + + #endregion } } \ No newline at end of file diff --git a/src/c#/GeneralUpdate.Core/Strategys/WindowsStrategy.cs b/src/c#/GeneralUpdate.Core/Strategys/WindowsStrategy.cs index 1cac9b82..9c123154 100644 --- a/src/c#/GeneralUpdate.Core/Strategys/WindowsStrategy.cs +++ b/src/c#/GeneralUpdate.Core/Strategys/WindowsStrategy.cs @@ -25,79 +25,79 @@ public class WindowsStrategy : AbstractStrategy public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter; - public override void Execute() + public override async Task ExecuteAsync() { - Task.Run(async () => + try { - try + var status = ReportType.None; + var patchPath = StorageManager.GetTempDirectory(Patchs); + foreach (var version in _configinfo.UpdateVersions) { - var status = ReportType.None; - var patchPath = StorageManager.GetTempDirectory(Patchs); - foreach (var version in _configinfo.UpdateVersions) + try { - try + var context = new PipelineContext(); + //Common + context.Add("ZipFilePath", + Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); + //Hash middleware + context.Add("Hash", version.Hash); + //Zip middleware + context.Add("Format", _configinfo.Format); + context.Add("Name", version.Name); + context.Add("Encoding", _configinfo.Encoding); + //Patch middleware + context.Add("SourcePath", _configinfo.InstallPath); + context.Add("PatchPath", patchPath); + context.Add("PatchEnabled", _configinfo.PatchEnabled); + //Driver middleware + if (_configinfo.DriveEnabled == true) { - var context = new PipelineContext(); - //Common - context.Add("ZipFilePath", - Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); - //Hash middleware - context.Add("Hash", version.Hash); - //Zip middleware - context.Add("Format", _configinfo.Format); - context.Add("Name", version.Name); - context.Add("Encoding", _configinfo.Encoding); - //Patch middleware - context.Add("SourcePath", _configinfo.InstallPath); - context.Add("PatchPath", patchPath); - context.Add("PatchEnabled", _configinfo.PatchEnabled); - //Driver middleware - if (_configinfo.DriveEnabled == true) - { - context.Add("DriverOutPut", StorageManager.GetTempDirectory("DriverOutPut")); - context.Add("FieldMappings", _configinfo.FieldMappings); - } - - var pipelineBuilder = new PipelineBuilder(context) - .UseMiddlewareIf(_configinfo.PatchEnabled) - .UseMiddleware() - .UseMiddleware() - .UseMiddlewareIf(_configinfo.DriveEnabled); - await pipelineBuilder.Build(); - status = ReportType.Success; + context.Add("DriverOutPut", StorageManager.GetTempDirectory("DriverOutPut")); + context.Add("FieldMappings", _configinfo.FieldMappings); } - catch (Exception e) - { - status = ReportType.Failure; - GeneralTracer.Error("The Execute method in the GeneralUpdate.Core.WindowsStrategy class throws an exception.", e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); - } - finally - { - await VersionService.Report(_configinfo.ReportUrl - , version.RecordId - , status - , version.AppType - , _configinfo.Scheme - , _configinfo.Token); - } - } - if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) + var pipelineBuilder = new PipelineBuilder(context) + .UseMiddlewareIf(_configinfo.PatchEnabled) + .UseMiddleware() + .UseMiddleware() + .UseMiddlewareIf(_configinfo.DriveEnabled); + await pipelineBuilder.Build(); + status = ReportType.Success; + } + catch (Exception e) { - OpenBrowser(_configinfo.UpdateLogUrl); + status = ReportType.Failure; + GeneralTracer.Error( + "The Execute method in the GeneralUpdate.Core.WindowsStrategy class throws an exception.", + e); + EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); + } + finally + { + await VersionService.Report(_configinfo.ReportUrl + , version.RecordId + , status + , version.AppType + , _configinfo.Scheme + , _configinfo.Token); } - - Clear(patchPath); - Clear(_configinfo.TempPath); - StartApp(); } - catch (Exception e) + + if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) { - GeneralTracer.Error("The Execute method in the GeneralUpdate.Core.WindowsStrategy class throws an exception.", e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); + OpenBrowser(_configinfo.UpdateLogUrl); } - }); + + Clear(patchPath); + Clear(_configinfo.TempPath); + StartApp(); + } + catch (Exception e) + { + GeneralTracer.Error( + "The Execute method in the GeneralUpdate.Core.WindowsStrategy class throws an exception.", e); + EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); + } } public override void StartApp() diff --git a/src/c#/GeneralUpdate.Upgrad/Program.cs b/src/c#/GeneralUpdate.Upgrad/Program.cs index 0db425ea..8ff0c8f6 100644 --- a/src/c#/GeneralUpdate.Upgrad/Program.cs +++ b/src/c#/GeneralUpdate.Upgrad/Program.cs @@ -4,6 +4,7 @@ using GeneralUpdate.Common.Internal; using GeneralUpdate.Common.Internal.Bootstrap; using GeneralUpdate.Common.Shared.Object; +using GeneralUpdate.Common.Shared.Object.Enum; using GeneralUpdate.Core; using GeneralUpdate.Core.Driver; @@ -18,6 +19,25 @@ static async Task Main(string[] args) Console.WriteLine($"升级程序初始化,{DateTime.Now}!"); Console.WriteLine("当前运行目录:" + Thread.GetDomain().BaseDirectory); await Task.Delay(2000); + var configinfo = new Configinfo + { + //configinfo.UpdateLogUrl = "https://www.baidu.com"; + ReportUrl = "http://127.0.0.1:5000/Upgrade/Report", + UpdateUrl = "http://127.0.0.1:5000/Upgrade/Verification", + AppName = "GeneralUpdate.Upgrad.exe", + MainAppName = "GeneralUpdate.Client.exe", + InstallPath = Thread.GetDomain().BaseDirectory, + //configinfo.Bowl = "Generalupdate.CatBowl.exe"; + //当前客户端的版本号 + ClientVersion = "1.0.0.0", + //当前升级端的版本号 + UpgradeClientVersion = "1.0.0.0", + //产品id + ProductId = "2d974e2a-31e6-4887-9bb1-b4689e98c77a", + //应用密钥 + AppSecretKey = "dfeb5833-975e-4afb-88f1-6278ee9aeff6", + Script = "linux/script.shell" + }; _ = await new GeneralUpdateBootstrap() //单个或多个更新包下载速度、剩余下载事件、当前下载版本信息通知事件 .AddListenerMultiDownloadStatistics(OnMultiDownloadStatistics) @@ -29,11 +49,15 @@ static async Task Main(string[] args) .AddListenerMultiDownloadError(OnMultiDownloadError) //整个更新过程出现的任何问题都会通过这个事件通知 .AddListenerException(OnException) + .SetConfig(configinfo) //设置字段映射表,用于解析所有驱动包的信息的字符串 //.SetFieldMappings(fieldMappingsCN) //是否开启驱动更新 //.Option(UpdateOption.Drive, true) //.Option(UpdateOption.Patch, false) + .Option(UpdateOption.DownloadTimeOut, 60) + .Option(UpdateOption.Encoding, Encoding.UTF8) + .Option(UpdateOption.Mode, UpdateMode.Scripts) .LaunchAsync(); Console.WriteLine($"升级程序已启动,{DateTime.Now}!"); } From c09430cae8c1d77b84c8ea4c907127f25ce2b94c Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Tue, 6 Jan 2026 23:28:02 +0800 Subject: [PATCH 02/11] Upgrade the NuGet versions referenced by the project --- src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj | 4 ++-- src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj | 5 +++++ .../GeneralUpdate.ClientCore.csproj | 6 +++--- src/c#/GeneralUpdate.Common/GeneralUpdate.Common.csproj | 6 +++--- src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj | 6 +++--- src/c#/GeneralUpdate.Upgrad/GeneralUpdate.Upgrad.csproj | 2 +- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj b/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj index c2a62b52..2b03c3a8 100644 --- a/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj +++ b/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj @@ -18,8 +18,8 @@ netstandard2.0; - - + + diff --git a/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj b/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj index 4980963a..511ec7ff 100644 --- a/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj +++ b/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj @@ -12,4 +12,9 @@ + + + + + diff --git a/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ClientCore.csproj b/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ClientCore.csproj index 25f13399..9907131b 100644 --- a/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ClientCore.csproj +++ b/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ClientCore.csproj @@ -84,9 +84,9 @@ - - - + + + diff --git a/src/c#/GeneralUpdate.Common/GeneralUpdate.Common.csproj b/src/c#/GeneralUpdate.Common/GeneralUpdate.Common.csproj index 7673c882..a63235db 100644 --- a/src/c#/GeneralUpdate.Common/GeneralUpdate.Common.csproj +++ b/src/c#/GeneralUpdate.Common/GeneralUpdate.Common.csproj @@ -18,9 +18,9 @@ netstandard2.0; - - - + + + diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj b/src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj index 87f9fec0..ac296dd1 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj +++ b/src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj @@ -92,9 +92,9 @@ - - - + + + diff --git a/src/c#/GeneralUpdate.Upgrad/GeneralUpdate.Upgrad.csproj b/src/c#/GeneralUpdate.Upgrad/GeneralUpdate.Upgrad.csproj index fa7565fe..c81e787c 100644 --- a/src/c#/GeneralUpdate.Upgrad/GeneralUpdate.Upgrad.csproj +++ b/src/c#/GeneralUpdate.Upgrad/GeneralUpdate.Upgrad.csproj @@ -13,7 +13,7 @@ - + all From 5f0d8ad1be8815817fcb00f89feafa7ad7c8dc62 Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Tue, 6 Jan 2026 23:35:28 +0800 Subject: [PATCH 03/11] Update GeneralUpdate.Client.csproj --- src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj b/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj index 511ec7ff..4980963a 100644 --- a/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj +++ b/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj @@ -12,9 +12,4 @@ - - - - - From 51ef4f2c20632a83f8742f53d8bfd553ea4d1c54 Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Wed, 7 Jan 2026 00:25:06 +0800 Subject: [PATCH 04/11] Update src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs index bef66f1d..138744e9 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs +++ b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs @@ -260,7 +260,7 @@ private static int GetPlatform() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return PlatformType.Windows; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return PlatformType.Linux; - return -1; + throw new PlatformNotSupportedException("The current operating system is not supported!"); } #endregion From 2f7344b87b3f120fe2b98d583ac4ec54d3b77d2a Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Wed, 7 Jan 2026 00:26:39 +0800 Subject: [PATCH 05/11] Update src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs index 138744e9..6cc98d36 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs +++ b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs @@ -232,10 +232,8 @@ private void ApplyRuntimeOptions() { _configInfo.Encoding = GetOption(UpdateOption.Encoding) ?? Encoding.Default; _configInfo.Format = GetOption(UpdateOption.Format) ?? Format.ZIP; - _configInfo.DownloadTimeOut = - GetOption(UpdateOption.DownloadTimeOut) == 0 - ? 60 - : GetOption(UpdateOption.DownloadTimeOut); + var downloadTimeoutOption = GetOption(UpdateOption.DownloadTimeOut); + _configInfo.DownloadTimeOut = downloadTimeoutOption ?? 60; _configInfo.DriveEnabled = GetOption(UpdateOption.Drive) ?? false; _configInfo.PatchEnabled = GetOption(UpdateOption.Patch) ?? true; } From fb846de94ec0e86fb147783fb025fa3775dc1eec Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Wed, 7 Jan 2026 00:27:32 +0800 Subject: [PATCH 06/11] Update src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs index 6cc98d36..19d587f2 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs +++ b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs @@ -282,6 +282,7 @@ protected override GeneralUpdateBootstrap StrategyFactory() private GeneralUpdateBootstrap AddListener(Action action) where TArgs : EventArgs { + if (action is null) throw new ArgumentNullException(nameof(action)); EventManager.Instance.AddListener(action); return this; } From 674a4f3c7ca85249ed26d95095a30d056284fb6d Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Wed, 7 Jan 2026 00:28:40 +0800 Subject: [PATCH 07/11] Update src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs b/src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs index b3fc7b0c..2cca3a9d 100644 --- a/src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs +++ b/src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs @@ -49,7 +49,7 @@ private class UpdateOptionPool : ConstantPool public static readonly UpdateOption BackUp = ValueOf("BACKUP"); /// - /// Whether to enable the backup function. + /// Specifies the update execution mode. /// public static readonly UpdateOption Mode = ValueOf("MODE"); From a79ba95a42b1c29fbfd6edde6ea56374c39c9718 Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Wed, 7 Jan 2026 00:29:39 +0800 Subject: [PATCH 08/11] Update src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../GeneralUpdate.Core/GeneralUpdateBootstrap.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs index 19d587f2..c684e9ca 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs +++ b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs @@ -246,8 +246,20 @@ private void InitBlackList() } private bool CanSkip(bool isForcibly) - => !isForcibly && _customSkipOption?.Invoke() == true; + { + if (isForcibly) + { + return false; + } + // Treat a null custom skip option as "do not skip". + if (_customSkipOption is null) + { + return false; + } + + return _customSkipOption(); + } private static bool CheckUpgrade(VersionRespDTO? response) => response?.Code == 200 && response.Body?.Count > 0; From af545676663c4118d48b2bd303e31f02a739aff3 Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Wed, 7 Jan 2026 00:30:46 +0800 Subject: [PATCH 09/11] Update src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../GeneralUpdate.Core/GeneralUpdateBootstrap.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs index c684e9ca..bf80b0d1 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs +++ b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs @@ -83,6 +83,21 @@ public GeneralUpdateBootstrap SetConfig(Configinfo configInfo) Script = configInfo.Script }; + // Copy blacklist-related configuration if explicitly provided. + if (configInfo.BlackFiles != null) + { + _configInfo.BlackFiles = configInfo.BlackFiles; + } + + if (configInfo.BlackFormats != null) + { + _configInfo.BlackFormats = configInfo.BlackFormats; + } + + if (configInfo.SkipDirectorys != null) + { + _configInfo.SkipDirectorys = configInfo.SkipDirectorys; + } InitBlackList(); return this; } From d41a8b70054326c2c6f7f98c0d9ffb44543f4378 Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Wed, 7 Jan 2026 00:31:03 +0800 Subject: [PATCH 10/11] Update src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs index bf80b0d1..a9e63796 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs +++ b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs @@ -108,9 +108,8 @@ public GeneralUpdateBootstrap SetFieldMappings(Dictionary fieldM return this; } - public GeneralUpdateBootstrap SetCustomSkipOption(Func func) + public GeneralUpdateBootstrap SetCustomSkipOption(Func? func) { - Debug.Assert(func != null); _customSkipOption = func; return this; } From ef74f98ed24f44581855e567c9632ace8dda55b9 Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Wed, 7 Jan 2026 00:44:50 +0800 Subject: [PATCH 11/11] Update src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs index a9e63796..32c49505 100644 --- a/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs +++ b/src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs @@ -78,6 +78,7 @@ public GeneralUpdateBootstrap SetConfig(Configinfo configInfo) UpdateUrl = configInfo.UpdateUrl, Scheme = configInfo.Scheme, Token = configInfo.Token, + ProductId = configInfo.ProductId, DriveEnabled = GetOption(UpdateOption.Drive) ?? false, PatchEnabled = GetOption(UpdateOption.Patch) ?? true, Script = configInfo.Script