mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-09 04:37:30 +02:00
Log WPF crash exceptions instead of showing Report problem UI (#39918)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Problem
-------------
We've observed multiple bug reports related to crashes with the
following exceptions:
System.Runtime.InteropServices.COMException (0xD0000701)
System.Runtime.InteropServices.COMException (0x80263001)
The root cause of these crashes has been traced to the WPF framework,
specifically this line in WindowChromeWorker.cs:
3439f20fb8/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Shell/WindowChromeWorker.cs (L1005)
These crashes are not necessarily caused by PowerToys Run itself being
used, or even visible. However, users perceive them as Run-related
because the "Report problem UI" is triggered by our global exception
handler, surfacing the underlying WPF crash.
Fix
------------
This PR:
- Suppresses the launch of the "Report problem UI" for exceptions known
to be triggered by unstable platform conditions (such as COMExceptions
from WPF internals).
- Continues to log the exception to preserve diagnostic data.
This change ensures we:
- Avoid showing an UI when WPF framework itself is already having
problem to handling DWM composition changes.
This commit is contained in:
@@ -14,25 +14,7 @@ namespace PowerLauncher.Helper
|
|||||||
{
|
{
|
||||||
public static class ErrorReporting
|
public static class ErrorReporting
|
||||||
{
|
{
|
||||||
private static void Report(Exception e, bool waitForClose)
|
private const string LoggerName = "UnHandledException";
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowMessageBox(string title, string message)
|
public static void ShowMessageBox(string title, string message)
|
||||||
{
|
{
|
||||||
@@ -47,17 +29,20 @@ namespace PowerLauncher.Helper
|
|||||||
// handle non-ui thread exceptions
|
// handle non-ui thread exceptions
|
||||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
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)
|
public static void DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
// handle ui thread exceptions
|
if (e != null)
|
||||||
Report(e?.Exception, false);
|
{
|
||||||
|
// handle ui thread exceptions
|
||||||
|
HandleException(e.Exception, false);
|
||||||
|
|
||||||
// prevent application exist, so the user can copy prompted error info
|
// prevent application exist, so the user can copy prompted error info
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string RuntimeInfo()
|
public static string RuntimeInfo()
|
||||||
@@ -68,5 +53,60 @@ namespace PowerLauncher.Helper
|
|||||||
$"\nx64: {Environment.Is64BitOperatingSystem}";
|
$"\nx64: {Environment.Is64BitOperatingSystem}";
|
||||||
return info;
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user