diff --git a/MAA.sln.DotSettings b/MAA.sln.DotSettings index cb91463023..dd72fd54c2 100644 --- a/MAA.sln.DotSettings +++ b/MAA.sln.DotSettings @@ -69,6 +69,7 @@ True True True + True True True True @@ -105,6 +106,7 @@ True True True + True True True diff --git a/src/MaaWpfGui/Configuration/ConfigFactory.cs b/src/MaaWpfGui/Configuration/ConfigFactory.cs index 050c6dcb54..64af5f7baf 100644 --- a/src/MaaWpfGui/Configuration/ConfigFactory.cs +++ b/src/MaaWpfGui/Configuration/ConfigFactory.cs @@ -240,15 +240,22 @@ namespace MaaWpfGui.Configuration private static async void OnPropertyChanged(string key, object? oldValue, object? newValue) { - var result = await SaveAsync(); - if (result) + try { - ConfigurationUpdateEvent?.Invoke(key, oldValue, newValue); - _logger.Debug("Configuration {Key} has been set to {Value}", key, newValue); + var result = await SaveAsync(); + if (result) + { + ConfigurationUpdateEvent?.Invoke(key, oldValue, newValue); + _logger.Debug($"Configuration {key} has been set to {newValue}"); + } + else + { + _logger.Warning($"Failed to save configuration {key} to {newValue}"); + } } - else + catch (Exception e) { - _logger.Warning("Failed to save configuration {Key} to {Value}", key, newValue); + _logger.Error(e, $"Failed to save configuration {key} to {newValue}, Exception: {e.Message}"); } } diff --git a/src/MaaWpfGui/Main/AsstProxy.cs b/src/MaaWpfGui/Main/AsstProxy.cs index 63307f23cf..311d95513f 100644 --- a/src/MaaWpfGui/Main/AsstProxy.cs +++ b/src/MaaWpfGui/Main/AsstProxy.cs @@ -396,7 +396,7 @@ namespace MaaWpfGui.Main { // 重置按钮状态,不影响LinkStart判断 _runningState.SetIdle(true); - Instances.TaskQueueViewModel.LinkStart(); + await Instances.TaskQueueViewModel.LinkStart(); } }); } @@ -975,7 +975,7 @@ namespace MaaWpfGui.Main } // Instances.TaskQueueViewModel.CheckAndShutdown(); - Instances.TaskQueueViewModel.CheckAfterCompleted(); + _ = Instances.TaskQueueViewModel.CheckAfterCompleted(); } else if (isCopilotTaskChain) { @@ -2170,6 +2170,11 @@ namespace MaaWpfGui.Main return AsstAppendTaskWithEncoding(TaskType.OperBox, AsstTaskType.OperBox) && AsstStart(); } + /// + /// 牛牛抽卡。 + /// + /// 是否为单抽,默认为 true + /// 是否成功。 public bool AsstStartGacha(bool once = true) { var task = new AsstCustomTask() @@ -2180,6 +2185,11 @@ namespace MaaWpfGui.Main return AsstAppendTaskWithEncoding(TaskType.Gacha, type, param) && AsstStart(); } + /// + /// 小游戏。 + /// + /// 任务名(tasks.json 中的 key) + /// 是否成功。 public bool AsstMiniGame(string taskName) { var task = new AsstCustomTask() @@ -2190,6 +2200,11 @@ namespace MaaWpfGui.Main return AsstAppendTaskWithEncoding(TaskType.MiniGame, type, param) && AsstStart(); } + /// + /// 视频识别。 + /// + /// 文件路径 + /// 是否成功。 public bool AsstStartVideoRec(string filename) { var taskParams = new JObject @@ -2201,12 +2216,12 @@ namespace MaaWpfGui.Main return id != 0 && AsstStart(); } - public bool AsstAppendTaskWithEncoding(TaskType wpfTasktype, (AsstTaskType Type, JObject? TaskParams) task) + public bool AsstAppendTaskWithEncoding(TaskType wpfTaskType, (AsstTaskType Type, JObject? TaskParams) task) { - return AsstAppendTaskWithEncoding(wpfTasktype, task.Type, task.TaskParams); + return AsstAppendTaskWithEncoding(wpfTaskType, task.Type, task.TaskParams); } - public bool AsstAppendTaskWithEncoding(TaskType wpfTasktype, AsstTaskType type, JObject? taskParams = null) + public bool AsstAppendTaskWithEncoding(TaskType wpfTaskType, AsstTaskType type, JObject? taskParams = null) { taskParams ??= []; AsstTaskId id = AsstAppendTask(_handle, type.ToString(), JsonConvert.SerializeObject(taskParams)); @@ -2215,7 +2230,7 @@ namespace MaaWpfGui.Main return false; } - _tasksStatus.Add(id, (wpfTasktype, TaskStatus.Idle)); + _tasksStatus.Add(id, (wpfTaskType, TaskStatus.Idle)); return true; } diff --git a/src/MaaWpfGui/Services/HotKeys/MaaHotKeyActionHandler.cs b/src/MaaWpfGui/Services/HotKeys/MaaHotKeyActionHandler.cs index 9a610761fd..8ca0725c4f 100644 --- a/src/MaaWpfGui/Services/HotKeys/MaaHotKeyActionHandler.cs +++ b/src/MaaWpfGui/Services/HotKeys/MaaHotKeyActionHandler.cs @@ -59,7 +59,7 @@ namespace MaaWpfGui.Services.HotKeys if (_runningState.GetIdle()) { - Instances.TaskQueueViewModel.LinkStart(); + _ = Instances.TaskQueueViewModel.LinkStart(); if (Instances.MainWindowManager.GetWindowState() != WindowState.Minimized) { diff --git a/src/MaaWpfGui/Services/RemoteControl/RemoteControlService.cs b/src/MaaWpfGui/Services/RemoteControl/RemoteControlService.cs index f5db787999..b173829143 100644 --- a/src/MaaWpfGui/Services/RemoteControl/RemoteControlService.cs +++ b/src/MaaWpfGui/Services/RemoteControl/RemoteControlService.cs @@ -377,7 +377,7 @@ namespace MaaWpfGui.Services.RemoteControl Instances.TaskQueueViewModel.AddLog(startLogStr); await Execute.OnUIThreadAsync(() => { - Instances.TaskQueueViewModel.LinkStart(); + _ = Instances.TaskQueueViewModel.LinkStart(); }); await _runningState.UntilIdleAsync(); @@ -395,14 +395,14 @@ namespace MaaWpfGui.Services.RemoteControl case "LinkStart-AutoRoguelike": case "LinkStart-Reclamation": { - await LinkStart(new[] { type.Split('-')[1] }); + await LinkStart([type.Split('-')[1]]); break; } case "Toolbox-GachaOnce": { await _runningState.UntilIdleAsync(); - Instances.RecognizerViewModel.GachaOnce(); + await Instances.RecognizerViewModel.GachaOnce(); await _runningState.UntilIdleAsync(); break; @@ -411,7 +411,7 @@ namespace MaaWpfGui.Services.RemoteControl case "Toolbox-GachaTenTimes": { await _runningState.UntilIdleAsync(); - Instances.RecognizerViewModel.GachaTenTimes(); + await Instances.RecognizerViewModel.GachaTenTimes(); await _runningState.UntilIdleAsync(); break; @@ -423,7 +423,7 @@ namespace MaaWpfGui.Services.RemoteControl bool connected = await Task.Run(() => Instances.AsstProxy.AsstConnect(ref errMsg)); if (connected) { - var image = Instances.AsstProxy.AsstGetImage(); + var image = await Instances.AsstProxy.AsstGetImageAsync(); if (image == null) { status = "FAILED"; diff --git a/src/MaaWpfGui/Utilities/BadModules.cs b/src/MaaWpfGui/Utilities/BadModules.cs index 7f5f0529f6..d671734406 100644 --- a/src/MaaWpfGui/Utilities/BadModules.cs +++ b/src/MaaWpfGui/Utilities/BadModules.cs @@ -1,3 +1,4 @@ +#nullable enable using System; using System.Collections.Generic; using System.Linq; @@ -12,13 +13,13 @@ namespace MaaWpfGui.Utilities { internal class BadModules { - private static string[] names = ["NahimicOSD.dll", "AudioDevProps2.dll"]; + private static readonly string[] _names = ["NahimicOSD.dll", "AudioDevProps2.dll"]; public static unsafe string[] GetBadInjectedModules() { var result = new List(); char[]? buffer = null; - foreach (var name in names) + foreach (var name in _names) { var hmod = PInvoke.GetModuleHandle(name); if (!hmod.IsInvalid) @@ -37,20 +38,20 @@ namespace MaaWpfGui.Utilities return result.ToArray(); } - private class WPFWin32Window : System.Windows.Forms.IWin32Window, System.Windows.Interop.IWin32Window + private class WpfWin32Window(System.Windows.Window w) : System.Windows.Forms.IWin32Window, System.Windows.Interop.IWin32Window { public IntPtr Handle => _helper.Handle; - private System.Windows.Interop.WindowInteropHelper _helper; - - public WPFWin32Window(System.Windows.Window w) - { - _helper = new System.Windows.Interop.WindowInteropHelper(w); - } + private readonly System.Windows.Interop.WindowInteropHelper _helper = new(w); } public static void CheckAndWarnBadInjectedModules() { + if (System.Windows.Application.Current.MainWindow is null) + { + return; + } + var allBadModules = GetBadInjectedModules(); var prevFound = ConfigFactory.Root.GUI.FoundBadModules.Split(";", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); var suppressed = ConfigFactory.Root.GUI.SuppressedBadModules.Split(";", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); @@ -92,7 +93,7 @@ namespace MaaWpfGui.Utilities }; } - TaskDialog.ShowDialog(new WPFWin32Window(System.Windows.Application.Current.MainWindow), page); + TaskDialog.ShowDialog(new WpfWin32Window(System.Windows.Application.Current.MainWindow), page); if (page.Verification?.Checked ?? false) { diff --git a/src/MaaWpfGui/ViewModels/UI/CopilotViewModel.cs b/src/MaaWpfGui/ViewModels/UI/CopilotViewModel.cs index f7dbc477dd..9c25012987 100644 --- a/src/MaaWpfGui/ViewModels/UI/CopilotViewModel.cs +++ b/src/MaaWpfGui/ViewModels/UI/CopilotViewModel.cs @@ -190,7 +190,7 @@ namespace MaaWpfGui.ViewModels.UI } else { - UpdateFilename(value); + _ = UpdateFilename(value); } } } @@ -391,8 +391,9 @@ namespace MaaWpfGui.ViewModels.UI /// /// Paste clipboard contents. /// + /// Task // ReSharper disable once UnusedMember.Global - public async void PasteClipboardCopilotSet() + public async Task PasteClipboardCopilotSet() { StartEnabled = false; UseCopilotList = true; @@ -408,8 +409,9 @@ namespace MaaWpfGui.ViewModels.UI /// /// 批量导入作业 /// + /// Task // ReSharper disable once UnusedMember.Global - public async void ImportFiles() + public async Task ImportFiles() { var dialog = new OpenFileDialog { @@ -450,7 +452,7 @@ namespace MaaWpfGui.ViewModels.UI } else if (payload is SSSCopilotModel) { - AddLog($"unsupport type: SSS", UiLogColor.Error, showTime: false); + AddLog("Unsupported type: SSS", UiLogColor.Error, showTime: false); } } catch @@ -463,16 +465,16 @@ namespace MaaWpfGui.ViewModels.UI // UI 绑定的方法 // ReSharper disable once UnusedMember.Global - public void AddCopilotTask() + public async Task AddCopilotTask() { - AddCopilotTaskToList(CopilotTaskName, false); + await AddCopilotTaskToList(CopilotTaskName, false); } // UI 绑定的方法 // ReSharper disable once UnusedMember.Global - public void AddCopilotTask_Adverse() + public async Task AddCopilotTask_Adverse() { - AddCopilotTaskToList(CopilotTaskName, true); + await AddCopilotTaskToList(CopilotTaskName, true); } // UI 绑定的方法 @@ -520,7 +522,7 @@ namespace MaaWpfGui.ViewModels.UI } // ReSharper disable once UnusedMember.Global - public async void LikeWebJson() + public async Task LikeWebJson() { CouldLikeWebJson = false; if (await RateCopilot(CopilotId) == PrtsStatus.Success) @@ -540,7 +542,7 @@ namespace MaaWpfGui.ViewModels.UI #endregion UI绑定及操作 - private async void UpdateFilename(string filename) + private async Task UpdateFilename(string filename) { StartEnabled = false; await UpdateFileDoc(filename); @@ -950,7 +952,7 @@ namespace MaaWpfGui.ViewModels.UI } } - private async void AddCopilotTaskToList(string? stageName, bool isRaid) + private async Task AddCopilotTaskToList(string? stageName, bool isRaid) { if (string.IsNullOrEmpty(stageName) || InvalidStageNameRegex().IsMatch(stageName)) { @@ -1116,9 +1118,10 @@ namespace MaaWpfGui.ViewModels.UI /// /// Starts copilot. /// + /// Task // UI 绑定的方法 // ReSharper disable once UnusedMember.Global - public async void Start() + public async Task Start() { /* if (_form) diff --git a/src/MaaWpfGui/ViewModels/UI/RecognizerViewModel.cs b/src/MaaWpfGui/ViewModels/UI/RecognizerViewModel.cs index 0a0d39d222..47a7ce62f0 100644 --- a/src/MaaWpfGui/ViewModels/UI/RecognizerViewModel.cs +++ b/src/MaaWpfGui/ViewModels/UI/RecognizerViewModel.cs @@ -53,7 +53,7 @@ namespace MaaWpfGui.ViewModels.UI DisplayName = LocalizationHelper.GetString("Toolbox"); _runningState = RunningState.Instance; _runningState.IdleChanged += RunningState_IdleChanged; - _peepImageTimer.Elapsed += RefreshPeepImageAsync; + _peepImageTimer.Elapsed += PeepImageTimerElapsed; _peepImageTimer.Interval = 1000d / PeepTargetFps; _gachaTimer.Tick += RefreshGachaTip; LoadDepotDetails(); @@ -188,9 +188,10 @@ namespace MaaWpfGui.ViewModels.UI /// /// Starts calculation. /// + /// Task // UI 绑定的方法 // ReSharper disable once UnusedMember.Global - public async void RecruitStartCalc() + public async Task RecruitStartCalc() { string errMsg = string.Empty; RecruitInfo = LocalizationHelper.GetString("ConnectingToEmulator"); @@ -496,9 +497,10 @@ namespace MaaWpfGui.ViewModels.UI /// /// Starts depot recognition. /// + /// Task // xaml 中用到了 // ReSharper disable once UnusedMember.Global - public async void StartDepot() + public async Task StartDepot() { _runningState.SetIdle(false); string errMsg = string.Empty; @@ -692,9 +694,10 @@ namespace MaaWpfGui.ViewModels.UI /// /// 开始识别干员 /// + /// Task /// xaml 中用到了 /// ReSharper disable once UnusedMember.Global - public async void StartOperBox() + public async Task StartOperBox() { _tempOperHaveSet = []; OperBoxHaveList = []; @@ -745,16 +748,16 @@ namespace MaaWpfGui.ViewModels.UI // xaml 中用到了 // ReSharper disable once UnusedMember.Global - public void GachaOnce() + public async Task GachaOnce() { - StartGacha(); + await StartGacha(); } // xaml 中用到了 // ReSharper disable once UnusedMember.Global - public void GachaTenTimes() + public async Task GachaTenTimes() { - StartGacha(false); + await StartGacha(false); } private bool _isGachaInProgress; @@ -776,7 +779,7 @@ namespace MaaWpfGui.ViewModels.UI } } - public async void StartGacha(bool once = true) + public async Task StartGacha(bool once = true) { _runningState.SetIdle(false); @@ -795,7 +798,7 @@ namespace MaaWpfGui.ViewModels.UI RefreshGachaTip(null, null); IsGachaInProgress = true; - Peep(); + _ = Peep(); } private void RefreshGachaTip(object? sender, EventArgs? e) @@ -953,7 +956,19 @@ namespace MaaWpfGui.ViewModels.UI private static int _peepImageSemaphoreFailCount = 0; private static readonly SemaphoreSlim _peepImageSemaphore = new(_peepImageSemaphoreCurrentCount, PeepImageSemaphoreMaxCount); - private async void RefreshPeepImageAsync(object? sender, EventArgs? e) + private async void PeepImageTimerElapsed(object? sender, EventArgs? e) + { + try + { + await RefreshPeepImageAsync(); + } + catch + { + // ignored + } + } + + private async Task RefreshPeepImageAsync() { if (!await _peepImageSemaphore.WaitAsync(0)) { @@ -1023,7 +1038,8 @@ namespace MaaWpfGui.ViewModels.UI /// /// 获取或停止获取实时截图,在抽卡时额外停止抽卡 /// - public async void Peep() + /// Task + public async Task Peep() { if (IsPeepTransitioning) { diff --git a/src/MaaWpfGui/ViewModels/UI/RootViewModel.cs b/src/MaaWpfGui/ViewModels/UI/RootViewModel.cs index b7d5ad286b..396ce97632 100644 --- a/src/MaaWpfGui/ViewModels/UI/RootViewModel.cs +++ b/src/MaaWpfGui/ViewModels/UI/RootViewModel.cs @@ -48,7 +48,7 @@ namespace MaaWpfGui.ViewModels.UI } InitViewModels(); - InitProxy(); + _ = InitProxy(); if (SettingsViewModel.VersionUpdateSettings.VersionType == VersionUpdateSettingsUserControlModel.UpdateVersionType.Nightly && !SettingsViewModel.VersionUpdateSettings.HasAcknowledgedNightlyWarning) { MessageBoxHelper.Show(LocalizationHelper.GetString("NightlyWarning")); @@ -76,9 +76,16 @@ namespace MaaWpfGui.ViewModels.UI _ = Instances.VersionUpdateViewModel.ShowUpdateOrDownload(); } - private static async void InitProxy() + private static async Task InitProxy() { - await Task.Run(Instances.AsstProxy.Init); + try + { + await Task.Run(Instances.AsstProxy.Init); + } + catch + { + // ignored + } } private void InitViewModels() diff --git a/src/MaaWpfGui/ViewModels/UI/TaskQueueViewModel.cs b/src/MaaWpfGui/ViewModels/UI/TaskQueueViewModel.cs index 409c5eebba..74c369c209 100644 --- a/src/MaaWpfGui/ViewModels/UI/TaskQueueViewModel.cs +++ b/src/MaaWpfGui/ViewModels/UI/TaskQueueViewModel.cs @@ -172,7 +172,8 @@ namespace MaaWpfGui.ViewModels.UI /// /// Checks after completion. /// - public async void CheckAfterCompleted() + /// Task + public async Task CheckAfterCompleted() { await Task.Run(() => SettingsViewModel.GameSettings.RunScript("EndsWithScript")); var actions = PostActionSetting; @@ -429,23 +430,30 @@ namespace MaaWpfGui.ViewModels.UI private async void Timer1_Elapsed(object sender, EventArgs e) { - // 提前记录时间,避免等待超过定时时间 - DateTime currentTime = DateTime.Now; - currentTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, currentTime.Hour, currentTime.Minute, 0); - - if (currentTime == _lastTimerElapsed) + try { - return; + // 提前记录时间,避免等待超过定时时间 + DateTime currentTime = DateTime.Now; + currentTime = new(currentTime.Year, currentTime.Month, currentTime.Day, currentTime.Hour, currentTime.Minute, 0); + + if (currentTime == _lastTimerElapsed) + { + return; + } + + _lastTimerElapsed = currentTime; + + HandleDatePromptUpdate(); + HandleCheckForUpdates(); + + InfrastTask.RefreshCustomInfrastPlanIndexByPeriod(); + + await HandleTimerLogic(currentTime); + } + catch + { + // ignored } - - _lastTimerElapsed = currentTime; - - HandleDatePromptUpdate(); - HandleCheckForUpdates(); - - InfrastTask.RefreshCustomInfrastPlanIndexByPeriod(); - - await HandleTimerLogic(currentTime); } private static int CalculateRandomDelay() @@ -629,7 +637,7 @@ namespace MaaWpfGui.ViewModels.UI InfrastTask.RefreshCustomInfrastPlanIndexByPeriod(); } - LinkStart(); + await LinkStart(); AchievementTrackerHelper.Instance.AddProgressToGroup(AchievementIds.ScheduleMasterGroup, 1); } @@ -1259,7 +1267,8 @@ namespace MaaWpfGui.ViewModels.UI /// /// Starts. /// - public async void LinkStart() + /// Task + public async Task LinkStart() { if (!_runningState.GetIdle()) { @@ -1473,7 +1482,7 @@ namespace MaaWpfGui.ViewModels.UI // UI 绑定的方法 // ReSharper disable once UnusedMember.Global - public async void WaitAndStop() + public async Task WaitAndStop() { Waiting = true; AddLog(LocalizationHelper.GetString("Waiting")); @@ -1527,7 +1536,7 @@ namespace MaaWpfGui.ViewModels.UI _runningState.SetIdle(true); } - public async void QuickSwitchAccount() + public async Task QuickSwitchAccount() { if (!_runningState.GetIdle()) { diff --git a/src/MaaWpfGui/ViewModels/UserControl/Settings/ConnectSettingsUserControlModel.cs b/src/MaaWpfGui/ViewModels/UserControl/Settings/ConnectSettingsUserControlModel.cs index 9988969f0d..4309544036 100644 --- a/src/MaaWpfGui/ViewModels/UserControl/Settings/ConnectSettingsUserControlModel.cs +++ b/src/MaaWpfGui/ViewModels/UserControl/Settings/ConnectSettingsUserControlModel.cs @@ -809,9 +809,10 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase /// /// Test Link And Get Image. /// + /// Task // UI 绑定的方法 // ReSharper disable once UnusedMember.Global - public async void TestLinkAndGetImage() + public async Task TestLinkAndGetImage() { _runningState.SetIdle(false); @@ -879,7 +880,7 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase var img = (Image)_imagePopupWindow.Content; img.MouseLeftButtonUp += (_, _) => { - TestLinkAndGetImage(); + _ = TestLinkAndGetImage(); }; } else @@ -983,7 +984,7 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase // UI 绑定的方法 // ReSharper disable once UnusedMember.Global - public async void ReplaceAdb() + public async Task ReplaceAdb() { if (string.IsNullOrEmpty(AdbPath)) { diff --git a/src/MaaWpfGui/ViewModels/UserControl/TaskQueue/StartUpSettingsUserControlModel.cs b/src/MaaWpfGui/ViewModels/UserControl/TaskQueue/StartUpSettingsUserControlModel.cs index 08a1d27c22..efb32ca3d5 100644 --- a/src/MaaWpfGui/ViewModels/UserControl/TaskQueue/StartUpSettingsUserControlModel.cs +++ b/src/MaaWpfGui/ViewModels/UserControl/TaskQueue/StartUpSettingsUserControlModel.cs @@ -48,7 +48,7 @@ public class StartUpSettingsUserControlModel : TaskViewModel // ReSharper disable once UnusedMember.Global public void AccountSwitchManualRun() { - Instances.TaskQueueViewModel.QuickSwitchAccount(); + _ = Instances.TaskQueueViewModel.QuickSwitchAccount(); } public override void ProcSubTaskMsg(AsstMsg msg, JObject details) diff --git a/src/MaaWpfGui/Views/UI/ErrorView.xaml.cs b/src/MaaWpfGui/Views/UI/ErrorView.xaml.cs index f6cfc85916..06b693a9b9 100644 --- a/src/MaaWpfGui/Views/UI/ErrorView.xaml.cs +++ b/src/MaaWpfGui/Views/UI/ErrorView.xaml.cs @@ -177,10 +177,17 @@ namespace MaaWpfGui.Views.UI private async void CopyErrorMessage_Click(object sender, RoutedEventArgs e) { - CopyToClipboard(); - CopiedTip.IsOpen = true; - await Task.Delay(3000); - CopiedTip.IsOpen = false; + try + { + CopyToClipboard(); + CopiedTip.IsOpen = true; + await Task.Delay(3000); + CopiedTip.IsOpen = false; + } + catch + { + // ignored + } } } }