Skip to content

Commit b44e525

Browse files
committed
Handle recoverable DWM composition exceptions gracefully
Updated the `ErrorReporting` class to log recoverable DWM composition exceptions instead of displaying the "Report problem UI," addressing issues with crashes in `PresentationFramework.dll`. Introduced a new `ExceptionHelper` class to encapsulate logic for identifying recoverable DWM composition exceptions based on specific HRESULT values and stack trace patterns. Added detailed comments for context and referenced a related GitHub issue. Improved modularity and maintainability by isolating exception handling logic in the `ExceptionHelper` class.
1 parent c6c4132 commit b44e525

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

Flow.Launcher/Helper/ErrorReporting.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ private static void Report(Exception e, bool silent = false, [CallerMemberName]
1616
var logger = LogManager.GetLogger(methodName);
1717
logger.Fatal(ExceptionFormatter.FormatExcpetion(e));
1818
if (silent) return;
19+
20+
// The crash occurs in PresentationFramework.dll, not necessarily when the Runner UI is visible, originating from this line:
21+
// https://github.com/dotnet/wpf/blob/3439f20fb8c685af6d9247e8fd2978cac42e74ac/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Shell/WindowChromeWorker.cs#L1005
22+
// Many bug reports because users see the "Report problem UI" after "the" crash with System.Runtime.InteropServices.COMException 0xD0000701 or 0x80263001.
23+
// 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.
24+
// This change modifies the behavior to log the exception instead of showing the "Report problem UI".
25+
if (ExceptionHelper.IsRecoverableDwmCompositionException(e as System.Runtime.InteropServices.COMException)) return;
26+
1927
var reportWindow = new ReportWindow(e);
2028
reportWindow.Show();
2129
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (c) Microsoft Corporation
2+
// The Microsoft Corporation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Runtime.InteropServices;
7+
8+
namespace Flow.Launcher.Helper;
9+
10+
internal static class ExceptionHelper
11+
{
12+
private const string PresentationFrameworkExceptionSource = "PresentationFramework";
13+
14+
private const int DWM_E_COMPOSITIONDISABLED = unchecked((int)0x80263001);
15+
16+
// HRESULT for NT STATUS STATUS_MESSAGE_LOST (0xC0000701 | 0x10000000 == 0xD0000701)
17+
private const int STATUS_MESSAGE_LOST_HR = unchecked((int)0xD0000701);
18+
19+
/// <summary>
20+
/// Returns true if the exception is a recoverable DWM composition exception.
21+
/// </summary>
22+
internal static bool IsRecoverableDwmCompositionException(Exception exception)
23+
{
24+
if (exception is not COMException comException)
25+
{
26+
return false;
27+
}
28+
29+
if (comException.HResult is DWM_E_COMPOSITIONDISABLED)
30+
{
31+
return true;
32+
}
33+
34+
if (comException.HResult is STATUS_MESSAGE_LOST_HR && comException.Source == PresentationFrameworkExceptionSource)
35+
{
36+
return true;
37+
}
38+
39+
// Check for common DWM composition changed patterns in the stack trace
40+
var stackTrace = comException.StackTrace;
41+
return !string.IsNullOrEmpty(stackTrace) &&
42+
stackTrace.Contains("DwmCompositionChanged");
43+
}
44+
}

0 commit comments

Comments
 (0)