mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-06-30 23:49:42 +02:00
Compare commits
3 Commits
v0.99.1
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c5d7237f9 | ||
|
|
2db77695c9 | ||
|
|
9db8e96c69 |
@@ -61,7 +61,7 @@ namespace PowerLauncher.Helper
|
||||
// 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 (ExceptionHelper.IsRecoverableDwmCompositionException(e as System.Runtime.InteropServices.COMException))
|
||||
if (ExceptionHelper.IsRecoverableDwmCompositionException(e))
|
||||
{
|
||||
var logger = LogManager.GetLogger(LoggerName);
|
||||
logger.Error($"From {(isNotUIThread ? "non" : string.Empty)} UI thread's exception: {ExceptionFormatter.FormatException(e)}");
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PowerLauncher.Helper
|
||||
@@ -22,6 +23,13 @@ namespace PowerLauncher.Helper
|
||||
/// </summary>
|
||||
internal static bool IsRecoverableDwmCompositionException(Exception exception)
|
||||
{
|
||||
// Unwrap TargetInvocationException to get the underlying exception, since WPF's internal
|
||||
// theme-change mechanism invokes handlers via reflection which wraps exceptions this way.
|
||||
if (exception is TargetInvocationException && exception.InnerException != null)
|
||||
{
|
||||
exception = exception.InnerException;
|
||||
}
|
||||
|
||||
if (exception is not COMException comException)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
@@ -160,12 +159,16 @@ namespace PowerLauncher.Helper
|
||||
|
||||
return;
|
||||
}
|
||||
catch (COMException ex) when (ExceptionHelper.IsRecoverableDwmCompositionException(ex))
|
||||
catch (Exception ex) when (ExceptionHelper.IsRecoverableDwmCompositionException(ex))
|
||||
{
|
||||
var logHResult = (ex is System.Reflection.TargetInvocationException tie && tie.InnerException != null)
|
||||
? tie.InnerException.HResult
|
||||
: ex.HResult;
|
||||
|
||||
switch (attempt)
|
||||
{
|
||||
case 1:
|
||||
Log.Warn($"Desktop composition is disabled (HRESULT: 0x{ex.HResult:X}). Scheduling retries for theme update.", typeof(ThemeManager));
|
||||
Log.Warn($"Desktop composition is disabled (HRESULT: 0x{logHResult:X}). Scheduling retries for theme update.", typeof(ThemeManager));
|
||||
delayMs = InitialDelayMs;
|
||||
break;
|
||||
case < maxAttempts:
|
||||
|
||||
118
src/modules/launcher/Wox.Test/ExceptionHelperTest.cs
Normal file
118
src/modules/launcher/Wox.Test/ExceptionHelperTest.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using PowerLauncher.Helper;
|
||||
|
||||
namespace Wox.Test;
|
||||
|
||||
[TestClass]
|
||||
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Win32 naming conventions")]
|
||||
public class ExceptionHelperTest
|
||||
{
|
||||
private const int DWM_E_COMPOSITIONDISABLED = unchecked((int)0x80263001);
|
||||
private const int STATUS_MESSAGE_LOST_HR = unchecked((int)0xD0000701);
|
||||
private const string PresentationFrameworkSource = "PresentationFramework";
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_NullException_ReturnsFalse()
|
||||
{
|
||||
Assert.IsFalse(ExceptionHelper.IsRecoverableDwmCompositionException(null));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_NonCOMException_ReturnsFalse()
|
||||
{
|
||||
var ex = new InvalidOperationException("Test");
|
||||
Assert.IsFalse(ExceptionHelper.IsRecoverableDwmCompositionException(ex));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_COMException_CompositionDisabled_ReturnsTrue()
|
||||
{
|
||||
var ex = new COMException("Desktop composition is disabled", DWM_E_COMPOSITIONDISABLED);
|
||||
Assert.IsTrue(ExceptionHelper.IsRecoverableDwmCompositionException(ex));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_COMException_OtherHResult_ReturnsFalse()
|
||||
{
|
||||
var ex = new COMException("Some other COM error", unchecked((int)0x80004005));
|
||||
Assert.IsFalse(ExceptionHelper.IsRecoverableDwmCompositionException(ex));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_TargetInvocationException_WrappingCompositionDisabled_ReturnsTrue()
|
||||
{
|
||||
var inner = new COMException("Desktop composition is disabled", DWM_E_COMPOSITIONDISABLED);
|
||||
var ex = new TargetInvocationException("Invocation failed", inner);
|
||||
Assert.IsTrue(ExceptionHelper.IsRecoverableDwmCompositionException(ex));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_TargetInvocationException_WrappingMessageLostFromPresentationFramework_ReturnsTrue()
|
||||
{
|
||||
var inner = new COMException("Message lost", STATUS_MESSAGE_LOST_HR)
|
||||
{
|
||||
Source = PresentationFrameworkSource,
|
||||
};
|
||||
var ex = new TargetInvocationException("Invocation failed", inner);
|
||||
Assert.IsTrue(ExceptionHelper.IsRecoverableDwmCompositionException(ex));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_TargetInvocationException_WrappingDwmCompositionChangedStackTrace_ReturnsTrue()
|
||||
{
|
||||
var inner = CreateDwmCompositionChangedComException();
|
||||
var ex = new TargetInvocationException("Invocation failed", inner);
|
||||
Assert.IsTrue(ExceptionHelper.IsRecoverableDwmCompositionException(ex));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_TargetInvocationException_WrappingUnrelatedCOMException_ReturnsFalse()
|
||||
{
|
||||
var inner = new COMException("Unrelated", unchecked((int)0x80004005));
|
||||
var ex = new TargetInvocationException("Invocation failed", inner);
|
||||
Assert.IsFalse(ExceptionHelper.IsRecoverableDwmCompositionException(ex));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_TargetInvocationException_WrappingNonCOMException_ReturnsFalse()
|
||||
{
|
||||
var inner = new InvalidOperationException("Not a COM exception");
|
||||
var ex = new TargetInvocationException("Invocation failed", inner);
|
||||
Assert.IsFalse(ExceptionHelper.IsRecoverableDwmCompositionException(ex));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsRecoverableDwmCompositionException_TargetInvocationException_NullInner_ReturnsFalse()
|
||||
{
|
||||
var ex = new TargetInvocationException("No inner", null);
|
||||
Assert.IsFalse(ExceptionHelper.IsRecoverableDwmCompositionException(ex));
|
||||
}
|
||||
|
||||
private static COMException CreateDwmCompositionChangedComException()
|
||||
{
|
||||
try
|
||||
{
|
||||
ThrowDwmCompositionChangedComException();
|
||||
throw new AssertFailedException("Expected COMException to be thrown.");
|
||||
}
|
||||
catch (COMException ex)
|
||||
{
|
||||
return ex;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void ThrowDwmCompositionChangedComException()
|
||||
{
|
||||
throw new COMException("DWM composition changed", unchecked((int)0x80004005));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user