diff --git a/src/modules/launcher/PowerLauncher/Helper/ErrorReporting.cs b/src/modules/launcher/PowerLauncher/Helper/ErrorReporting.cs index 3eb6252a24..5003a02cae 100644 --- a/src/modules/launcher/PowerLauncher/Helper/ErrorReporting.cs +++ b/src/modules/launcher/PowerLauncher/Helper/ErrorReporting.cs @@ -14,25 +14,7 @@ namespace PowerLauncher.Helper { public static class ErrorReporting { - private static void Report(Exception e, bool waitForClose) - { - if (e != null) - { - var logger = LogManager.GetLogger("UnHandledException"); - logger.Fatal(ExceptionFormatter.FormatException(e)); - - var reportWindow = new ReportWindow(e); - - if (waitForClose) - { - reportWindow.ShowDialog(); - } - else - { - reportWindow.Show(); - } - } - } + private const string LoggerName = "UnHandledException"; public static void ShowMessageBox(string title, string message) { @@ -47,17 +29,20 @@ namespace PowerLauncher.Helper // handle non-ui thread exceptions System.Windows.Application.Current.Dispatcher.Invoke(() => { - Report((Exception)e?.ExceptionObject, true); + HandleException(e?.ExceptionObject as Exception, true); }); } public static void DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { - // handle ui thread exceptions - Report(e?.Exception, false); + if (e != null) + { + // handle ui thread exceptions + HandleException(e.Exception, false); - // prevent application exist, so the user can copy prompted error info - e.Handled = true; + // prevent application exist, so the user can copy prompted error info + e.Handled = true; + } } public static string RuntimeInfo() @@ -68,5 +53,60 @@ namespace PowerLauncher.Helper $"\nx64: {Environment.Is64BitOperatingSystem}"; return info; } + + private static void HandleException(Exception e, bool isNotUIThread) + { + // The crash occurs in PresentationFramework.dll, not necessarily when the Runner UI is visible, originating from this line: + // https://github.com/dotnet/wpf/blob/3439f20fb8c685af6d9247e8fd2978cac42e74ac/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Shell/WindowChromeWorker.cs#L1005 + // Many bug reports because users see the "Report problem UI" after "the" crash with System.Runtime.InteropServices.COMException 0xD0000701 or 0x80263001. + // However, displaying this "Report problem UI" during WPF crashes, especially when DWM composition is changing, is not ideal; some users reported it hangs for up to a minute before the "Report problem UI" appears. + // This change modifies the behavior to log the exception instead of showing the "Report problem UI". + if (IsDwmCompositionException(e as System.Runtime.InteropServices.COMException)) + { + var logger = LogManager.GetLogger(LoggerName); + logger.Error($"From {(isNotUIThread ? "non" : string.Empty)} UI thread's exception: {ExceptionFormatter.FormatException(e)}"); + } + else + { + Report(e, isNotUIThread); + } + } + + private static void Report(Exception e, bool waitForClose) + { + if (e != null) + { + var logger = LogManager.GetLogger(LoggerName); + logger.Fatal($"From {(waitForClose ? "non" : string.Empty)} UI thread's exception: {ExceptionFormatter.FormatException(e)}"); + + var reportWindow = new ReportWindow(e); + + if (waitForClose) + { + reportWindow.ShowDialog(); + } + else + { + reportWindow.Show(); + } + } + } + + private static bool IsDwmCompositionException(System.Runtime.InteropServices.COMException comException) + { + if (comException == null) + { + return false; + } + + var stackTrace = comException.StackTrace; + if (string.IsNullOrEmpty(stackTrace)) + { + return false; + } + + // Check for common DWM composition changed patterns in the stack trace + return stackTrace.Contains("DwmCompositionChanged"); + } } }