diff --git a/src/MaaWpfGui/Configuration/GUI.cs b/src/MaaWpfGui/Configuration/GUI.cs index c284bd2d82..72b74526fb 100644 --- a/src/MaaWpfGui/Configuration/GUI.cs +++ b/src/MaaWpfGui/Configuration/GUI.cs @@ -51,6 +51,10 @@ namespace MaaWpfGui.Configuration public string WindowTitlePrefix { get; set; } = string.Empty; + public string FoundBadModules { get; set; } = string.Empty; + + public string SuppressedBadModules { get; set; } = string.Empty; + // ReSharper disable once UnusedMember.Global public void OnPropertyChanged(string propertyName, object before, object after) { diff --git a/src/MaaWpfGui/Main/Bootstrapper.cs b/src/MaaWpfGui/Main/Bootstrapper.cs index 503a07022d..01de401148 100644 --- a/src/MaaWpfGui/Main/Bootstrapper.cs +++ b/src/MaaWpfGui/Main/Bootstrapper.cs @@ -37,6 +37,7 @@ using MaaWpfGui.Services.Managers; using MaaWpfGui.Services.RemoteControl; using MaaWpfGui.Services.Web; using MaaWpfGui.States; +using MaaWpfGui.Utilities; using MaaWpfGui.ViewModels.UI; using MaaWpfGui.ViewModels.UserControl.Settings; using MaaWpfGui.Views.UI; @@ -237,6 +238,11 @@ namespace MaaWpfGui.Main } } + protected override void OnLaunch() + { + BadModules.CheckAndWarnBadInjectedModules(); + } + private static bool HandleMultipleInstances() { // 设置互斥量的名称 diff --git a/src/MaaWpfGui/NativeMethods.txt b/src/MaaWpfGui/NativeMethods.txt index 4f0c5c8778..07929c9816 100644 --- a/src/MaaWpfGui/NativeMethods.txt +++ b/src/MaaWpfGui/NativeMethods.txt @@ -24,3 +24,7 @@ TD_ERROR_ICON TD_WARNING_ICON TD_INFORMATION_ICON SHGetStockIconInfo + +//BadInjectedDllChecker +GetModuleHandle +GetModuleFileName diff --git a/src/MaaWpfGui/Res/Localizations/en-us.xaml b/src/MaaWpfGui/Res/Localizations/en-us.xaml index 5bc646e4c4..b72eca1be0 100644 --- a/src/MaaWpfGui/Res/Localizations/en-us.xaml +++ b/src/MaaWpfGui/Res/Localizations/en-us.xaml @@ -1367,4 +1367,11 @@ If you want to run multiple MAA at the same time, please copy the whole MAA and Immortal MAA truly immortal. Clear any I.S. at N15 difficulty or above with MAA + + + Compatibility Warning + The following DLL(s) injected into MAA may crash MAA or corrupt MAA user interface: + If you encounter such issues with MAA, please try adding MAA to the exclusion list of the relevant software, or uninstall the related software and check if the problem persists. + Do not show this warning again + diff --git a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml index 40c0c47cc3..b65a673202 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml @@ -1371,4 +1371,11 @@ C:\\leidian\\LDPlayer9。\n 仙术牛牛真仙术。 使用牛牛通关任意肉鸽 N15 以上难度 + + + 悲报 + 以下注入到 MAA 的 DLL 可能会导致 MAA 闪退或界面渲染异常: + 如果您注意到 MAA 存在相关问题,请尝试将 MAA 加入相关软件的排除名单,或卸载相关软件后检查问题是否仍然存在。 + 不再显示此警告 + diff --git a/src/MaaWpfGui/Utilities/BadModules.cs b/src/MaaWpfGui/Utilities/BadModules.cs new file mode 100644 index 0000000000..7f5f0529f6 --- /dev/null +++ b/src/MaaWpfGui/Utilities/BadModules.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using MaaWpfGui.Configuration; +using MaaWpfGui.Helper; +using Windows.Win32; + +namespace MaaWpfGui.Utilities +{ + internal class BadModules + { + private static string[] names = ["NahimicOSD.dll", "AudioDevProps2.dll"]; + + public static unsafe string[] GetBadInjectedModules() + { + var result = new List(); + char[]? buffer = null; + foreach (var name in names) + { + var hmod = PInvoke.GetModuleHandle(name); + if (!hmod.IsInvalid) + { + buffer ??= new char[65536]; + fixed (char* ptr = buffer) + { + if (PInvoke.GetModuleFileName(hmod, ptr, 65536) > 0) + { + result.Add(new string(ptr)); + } + } + } + } + + return result.ToArray(); + } + + private class WPFWin32Window : 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); + } + } + + public static void CheckAndWarnBadInjectedModules() + { + 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); + var newFoundBadModules = allBadModules.Where(x => !prevFound.Contains(x, StringComparer.InvariantCultureIgnoreCase)).ToArray(); + var notSuppressedBadModules = allBadModules.Where(x => !suppressed.Contains(x, StringComparer.InvariantCultureIgnoreCase)).ToArray(); + ConfigFactory.Root.GUI.FoundBadModules = string.Join(";", [.. prevFound, .. newFoundBadModules]); + + if (notSuppressedBadModules.Length > 0) + { + var sb = new StringBuilder(); + sb.AppendLine(LocalizationHelper.GetString("BadModules.Warning.Prolog")); + sb.AppendLine(); + foreach (var module in allBadModules) + { + sb.AppendLine(module); + } + + sb.AppendLine(); + + sb.Append(LocalizationHelper.GetString("BadModules.Warning.Epilog")); + + var page = new TaskDialogPage + { + Caption = "MAA", + Heading = LocalizationHelper.GetString("BadModules.Warning.Heading"), + Text = sb.ToString(), + Icon = TaskDialogIcon.Warning, + Buttons = { TaskDialogButton.OK }, + SizeToContent = true, + }; + + if (newFoundBadModules.Length == 0) + { + // only show the "Do not show again" checkbox on the second time + page.Verification = new() + { + Text = LocalizationHelper.GetString("BadModules.Warning.DoNotShowAgain"), + Checked = false, + }; + } + + TaskDialog.ShowDialog(new WPFWin32Window(System.Windows.Application.Current.MainWindow), page); + + if (page.Verification?.Checked ?? false) + { + ConfigFactory.Root.GUI.SuppressedBadModules = string.Join(";", allBadModules); + } + } + } + } +}