diff --git a/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs b/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs index c839e38f..d4f75def 100644 --- a/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs +++ b/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs @@ -56,6 +56,12 @@ public class ScriptRepoUpdater : Singleton /// public event EventHandler? AutoUpdateStateChanged; + /// + /// 命令行启动时并行执行的自动更新 Task。 + /// StartGameTask 结束后会 await 此 Task,确保更新完成后再执行任务。 + /// + public Task? CommandLineAutoUpdateTask { get; set; } + // 仓储位置 public static readonly string ReposPath = Global.Absolute("Repos"); diff --git a/BetterGenshinImpact/Helpers/CommandLineOptions.cs b/BetterGenshinImpact/Helpers/CommandLineOptions.cs new file mode 100644 index 00000000..b48c40cc --- /dev/null +++ b/BetterGenshinImpact/Helpers/CommandLineOptions.cs @@ -0,0 +1,96 @@ +using System; +using System.Linq; + +namespace BetterGenshinImpact.Helpers; + +/// +/// 命令行参数统一解析,启动时解析一次,各处查询解析结果。 +/// +public class CommandLineOptions +{ + private static CommandLineOptions? _instance; + + public static CommandLineOptions Instance => _instance ??= Parse(Environment.GetCommandLineArgs()); + + public CommandLineAction Action { get; } + + /// + /// startOneDragon 时可选的配置名称(第 3 个参数) + /// + public string? OneDragonConfigName { get; } + + /// + /// --startGroups / --TaskProgress 时传入的组名列表(第 3 个参数起) + /// + public string[] GroupNames { get; } = []; + + /// + /// 是否有命令行任务参数(startOneDragon / --startGroups / --TaskProgress / start) + /// + public bool HasTaskArgs => Action != CommandLineAction.None; + + /// + /// 是否是需要 StartGameTask 自行处理游戏启动的命令 + /// (一条龙、配置组、任务进度由各自流程中的 StartGameTask 启动游戏) + /// + public bool ShouldDeferGameStart => Action is CommandLineAction.StartOneDragon + or CommandLineAction.StartGroups + or CommandLineAction.TaskProgress; + + private CommandLineOptions(CommandLineAction action, string? oneDragonConfigName = null, string[]? groupNames = null) + { + Action = action; + OneDragonConfigName = oneDragonConfigName; + GroupNames = groupNames ?? []; + } + + internal static CommandLineOptions Parse(string[] args) + { + if (args.Length <= 1) + return new CommandLineOptions(CommandLineAction.None); + + var arg1 = args[1].Trim(); + var extra = args.Skip(2).Select(x => x.Trim()).ToArray(); + + if (arg1.Contains("startOneDragon", StringComparison.OrdinalIgnoreCase)) + { + return new CommandLineOptions(CommandLineAction.StartOneDragon, + oneDragonConfigName: extra.Length > 0 ? extra[0] : null); + } + + if (arg1.Equals("--startGroups", StringComparison.OrdinalIgnoreCase)) + { + return new CommandLineOptions(CommandLineAction.StartGroups, groupNames: extra); + } + + if (arg1.Equals("--TaskProgress", StringComparison.OrdinalIgnoreCase)) + { + return new CommandLineOptions(CommandLineAction.TaskProgress, groupNames: extra); + } + + if (arg1.Contains("start", StringComparison.OrdinalIgnoreCase)) + { + return new CommandLineOptions(CommandLineAction.Start); + } + + return new CommandLineOptions(CommandLineAction.None); + } +} + +public enum CommandLineAction +{ + /// 双击启动,无命令行参数 + None, + + /// 纯 "start" — 仅启动截图器 + Start, + + /// startOneDragon — 启动一条龙 + StartOneDragon, + + /// --startGroups — 启动调度组 + StartGroups, + + /// --TaskProgress — 启动任务进度 + TaskProgress, +} diff --git a/BetterGenshinImpact/Service/ApplicationHostService.cs b/BetterGenshinImpact/Service/ApplicationHostService.cs index a05c9c60..5baa95b4 100644 --- a/BetterGenshinImpact/Service/ApplicationHostService.cs +++ b/BetterGenshinImpact/Service/ApplicationHostService.cs @@ -9,8 +9,7 @@ using System.Threading.Tasks; using System.Windows; using BetterGenshinImpact.Core.Script; using BetterGenshinImpact.GameTask; -using BetterGenshinImpact.GameTask.Common; -using Microsoft.Extensions.Logging; +using BetterGenshinImpact.Helpers; using Wpf.Ui; namespace BetterGenshinImpact.Service; @@ -49,66 +48,56 @@ public class ApplicationHostService(IServiceProvider serviceProvider) : IHostedS { _navigationWindow = (serviceProvider.GetService(typeof(INavigationWindow)) as INavigationWindow)!; _navigationWindow!.ShowWindow(); - // - var args = Environment.GetCommandLineArgs(); - if (args.Length > 1) + var cmdOptions = CommandLineOptions.Instance; + + if (cmdOptions.HasTaskArgs) { - //无论如何,先跳到主页,否则在通过参数的任务在执行完之前,不会加载快捷键 _ = _navigationWindow.Navigate(typeof(HomePage)); - // 命令行启动时,先等待自动更新订阅脚本完成,再运行配置组/一条龙 - // (正常双击启动在 MainWindowViewModel.OnLoaded 中以 fire-and-forget 方式调用) + // 命令行启动时,并行更新订阅脚本(不阻塞游戏启动和导航) + // StartGameTask 会在游戏进入主界面后等待此 Task 完成,再开始执行任务 var scriptConfig = TaskContext.Instance().Config.ScriptConfig; if (scriptConfig.AutoUpdateBeforeCommandLineRun) { - await Task.Run(() => ScriptRepoUpdater.Instance.AutoUpdateSubscribedScripts()); + ScriptRepoUpdater.Instance.CommandLineAutoUpdateTask = + Task.Run(() => ScriptRepoUpdater.Instance.AutoUpdateSubscribedScripts()); } - if (args[1].Contains("startOneDragon", StringComparison.InvariantCultureIgnoreCase)) + switch (cmdOptions.Action) { + case CommandLineAction.StartOneDragon: + // 通过命令行参数启动「一条龙」 => 跳转到一条龙配置页。 + _ = _navigationWindow.Navigate(typeof(OneDragonFlowPage)); + // 后续代码在 OneDragonFlowViewModel / OnLoaded 中。 + break; - // 通过命令行参数启动「一条龙」 => 跳转到一条龙配置页。 - _ = _navigationWindow.Navigate(typeof(OneDragonFlowPage)); - // 后续代码在 OneDragonFlowViewModel / OnLoaded 中。 - } - else if (args[1].Trim().Equals("--startGroups", StringComparison.InvariantCultureIgnoreCase)) - { - // 通过命令行参数启动「调度组」 => 跳转到调度器配置页。 - _ = _navigationWindow.Navigate(typeof(ScriptControlPage)); - if (args.Length > 2) - { - // 获取调度组 - var names = args.Skip(2).ToArray().Select(x => x.Trim()).ToArray(); - // 启动调度器 - var scheduler = App.GetService(); - scheduler?.OnStartMultiScriptGroupWithNamesAsync(names); - } - }else if (args[1].Trim().Equals("--TaskProgress", StringComparison.InvariantCultureIgnoreCase)) - { + case CommandLineAction.StartGroups: + // 通过命令行参数启动「调度组」 => 跳转到调度器配置页。 + _ = _navigationWindow.Navigate(typeof(ScriptControlPage)); + if (cmdOptions.GroupNames.Length > 0) + { + var scheduler = App.GetService(); + scheduler?.OnStartMultiScriptGroupWithNamesAsync(cmdOptions.GroupNames); + } + break; - // 通过命令行参数启动「调度组」 => 跳转到调度器配置页。 - _ = _navigationWindow.Navigate(typeof(ScriptControlPage)); - if (args.Length > 1) - { - // 获取调度组 - var names = args.Skip(2).ToArray().Select(x => x.Trim()).ToArray(); - // 启动调度器 - var scheduler = App.GetService(); - scheduler?.OnStartMultiScriptTaskProgressAsync(names); - } - } - else if (args[1].Contains("start")) - { - // 通过命令行参数打开「启动页开关」 => 跳转到主页。 - _ = _navigationWindow.Navigate(typeof(HomePage)); - // 后续代码在 HomePageViewModel / OnLoaded 中。 - } - else - { - // 其它命令行参数 => 跳转到主页。 - _ = _navigationWindow.Navigate(typeof(HomePage)); + case CommandLineAction.TaskProgress: + // 通过命令行参数启动「任务进度」 => 跳转到调度器配置页。 + _ = _navigationWindow.Navigate(typeof(ScriptControlPage)); + if (cmdOptions.GroupNames.Length > 0) + { + var scheduler = App.GetService(); + scheduler?.OnStartMultiScriptTaskProgressAsync(cmdOptions.GroupNames); + } + break; + + case CommandLineAction.Start: + // 通过命令行参数打开「启动页开关」 => 跳转到主页。 + _ = _navigationWindow.Navigate(typeof(HomePage)); + // 后续代码在 HomePageViewModel / OnLoaded 中。 + break; } } else diff --git a/BetterGenshinImpact/Service/ScriptService.cs b/BetterGenshinImpact/Service/ScriptService.cs index 83d44591..f30fd8eb 100644 --- a/BetterGenshinImpact/Service/ScriptService.cs +++ b/BetterGenshinImpact/Service/ScriptService.cs @@ -621,5 +621,13 @@ public partial class ScriptService : IScriptService }); } } + + // 等待命令行启动时并行执行的自动更新完成(如果有) + var pendingUpdate = ScriptRepoUpdater.Instance.CommandLineAutoUpdateTask; + if (pendingUpdate != null) + { + await pendingUpdate; + ScriptRepoUpdater.Instance.CommandLineAutoUpdateTask = null; + } } } diff --git a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs index 2320885b..77ee76be 100644 --- a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs +++ b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs @@ -250,7 +250,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel // 预热OCR await OcrPreheating(); - if (Environment.GetCommandLineArgs().Length > 1) + if (CommandLineOptions.Instance.HasTaskArgs) { return; } diff --git a/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs index 3777949f..c5462997 100644 --- a/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs @@ -133,8 +133,9 @@ public partial class HomePageViewModel : ViewModel _autoRun = false; - var args = Environment.GetCommandLineArgs(); - if (args.Length > 1 && args[1].Contains("start")) + // 只对纯 "start" 参数自动启动截图器 + // startOneDragon、--startGroups 等由各自流程中的 StartGameTask 处理 + if (CommandLineOptions.Instance.Action == CommandLineAction.Start) { _ = OnStartTriggerAsync(); } diff --git a/BetterGenshinImpact/ViewModel/Pages/OneDragonFlowViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/OneDragonFlowViewModel.cs index 142c81df..97413ba3 100644 --- a/BetterGenshinImpact/ViewModel/Pages/OneDragonFlowViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/OneDragonFlowViewModel.cs @@ -545,15 +545,16 @@ public partial class OneDragonFlowViewModel : ViewModel } _autoRun = false; // - var args = Environment.GetCommandLineArgs(); - if (args.Length > 1 && args[1].Contains("startOneDragon")) + var cmdOptions = CommandLineOptions.Instance; + if (cmdOptions.Action == CommandLineAction.StartOneDragon) { // 通过命令行参数启动一条龙。 - if (args.Length > 2) + if (cmdOptions.OneDragonConfigName != null) { // 从命令行参数中提取一条龙配置名称。 - _logger.LogInformation($"参数指定的一条龙配置:{args[2]}"); - var argsOneDragonConfig = ConfigList.FirstOrDefault(x => x.Name == args[2], null); + _logger.LogInformation($"参数指定的一条龙配置:{cmdOptions.OneDragonConfigName}"); + var argsOneDragonConfig = ConfigList.FirstOrDefault(x => + string.Equals(x.Name, cmdOptions.OneDragonConfigName, StringComparison.Ordinal)); if (argsOneDragonConfig != null) { // 设定配置,配置下拉框会选定。