From 1096a49dd6fb3e879c919e0b9e43ae5a9af38cd1 Mon Sep 17 00:00:00 2001 From: goat Date: Tue, 11 Apr 2023 19:27:26 +0200 Subject: [PATCH] feat: show throwing plugin in unhandled managed exceptions --- Dalamud/EntryPoint.cs | 22 +++++++++++++++++++++- Dalamud/Plugin/Internal/PluginManager.cs | 14 +++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index 9cd31d7ae..8fa9e70a0 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Dalamud.Configuration.Internal; using Dalamud.Logging.Internal; +using Dalamud.Plugin.Internal; using Dalamud.Support; using Dalamud.Utility; using Newtonsoft.Json; @@ -325,10 +326,29 @@ public sealed class EntryPoint info = $"{ex.TargetSite.DeclaringType.Assembly.GetName().Name}, {ex.TargetSite.DeclaringType.FullName}::{ex.TargetSite.Name}"; } + var pluginInfo = string.Empty; + var supportText = ", please visit us on Discord for more help."; + try + { + var pm = Service.GetNullable(); + var plugin = pm?.FindCallingPlugin(new StackTrace(ex)); + if (plugin != null) + { + pluginInfo = $"Plugin that caused this:\n{plugin.Name}\n\nClick \"Yes\" and remove it.\n\n"; + + if (plugin.Manifest.IsThirdParty) + supportText = string.Empty; + } + } + catch + { + // ignored + } + const MessageBoxType flags = NativeFunctions.MessageBoxType.YesNo | NativeFunctions.MessageBoxType.IconError | NativeFunctions.MessageBoxType.SystemModal; var result = MessageBoxW( Process.GetCurrentProcess().MainWindowHandle, - $"An internal error in a Dalamud plugin occurred.\nThe game must close.\n\nType: {ex.GetType().Name}\n{info}\n\nMore information has been recorded separately, please contact us in our Discord or on GitHub.\n\nDo you want to disable all plugins the next time you start the game?", + $"An internal error in a Dalamud plugin occurred.\nThe game must close.\n\n{ex.GetType().Name}\n{info}\n\n{pluginInfo}More information has been recorded separately{supportText}.\n\nDo you want to disable all plugins the next time you start the game?", "Dalamud", flags); diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 311172c97..28d696a86 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -1300,14 +1300,14 @@ Thanks and have fun!"; } /// - /// Get the plugin that called this method by walking the stack, + /// Get the plugin that called this method by walking the provided stack trace, /// or null, if it cannot be determined. /// At the time, this is naive and shouldn't be used for security-critical checks. /// + /// The trace to walk. /// The calling plugin, or null. - public LocalPlugin? FindCallingPlugin() + public LocalPlugin? FindCallingPlugin(StackTrace trace) { - var trace = new StackTrace(); foreach (var frame in trace.GetFrames()) { var declaringType = frame.GetMethod()?.DeclaringType; @@ -1328,6 +1328,14 @@ Thanks and have fun!"; return null; } + /// + /// Get the plugin that called this method by walking the stack, + /// or null, if it cannot be determined. + /// At the time, this is naive and shouldn't be used for security-critical checks. + /// + /// The calling plugin, or null. + public LocalPlugin? FindCallingPlugin() => this.FindCallingPlugin(new StackTrace()); + private void DetectAvailablePluginUpdates() { var updatablePlugins = new List();