mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-07-09 03:49:52 +02:00
## Summary Adds the two missing top-level exception handlers in the QuickAccess (Preview) flyout host so that an unhandled XAML exception during launch or page navigation no longer FailFasts `PowerToys.QuickAccess.exe`. Spotted while reading through `App.OnLaunched` and `ShellPage` for an unrelated review of the flyout startup path — none of the existing handlers exist yet, so any throw during `MainWindow` construction, `ShellHost.Initialize`, or `ContentFrame.Navigate(typeof(LaunchPage) | typeof(AppsListPage), …)` bubbles all the way out to the Windows App SDK runtime and is stowed as a XAML failure. Compare with `src\settings-ui\Settings.UI\SettingsXAML\App.xaml.cs`, which already wires `UnhandledException += App_UnhandledException`. ## Changes **`src\settings-ui\QuickAccess.UI\QuickAccessXAML\App.xaml.cs`** - Hook `Application.UnhandledException` in the constructor. The handler logs the exception via `ManagedCommon.Logger.LogError` (same logger Settings uses) and sets `e.Handled = true`. QuickAccess is a transient launcher flyout owned by the runner, so swallowing a stray XAML error and keeping the host alive for the next summon is the correct trade-off — the failure is still recorded for diagnostics. - Wrap the body of `OnLaunched` in a try/catch. If `MainWindow` (which sets up window chrome, listener threads, the IPC coordinator, and the XAML shell) fails to construct, log the exception and call `Exit()` cleanly rather than letting the throw escape into the Windows App SDK launch path. **`src\settings-ui\QuickAccess.UI\QuickAccessXAML\Flyout\ShellPage.xaml.cs`** - Subscribe to `ContentFrame.NavigationFailed` after `InitializeComponent`. A page constructor or XAML-load failure in `LaunchPage` / `AppsListPage` would otherwise bubble out of the `Frame` and crash the launcher. The handler logs the failure (`SourcePageType.FullName` + the exception) and marks it handled so the next summon retries navigation. No production behaviour changes when things work — only the failure paths are different. No public API surface changes. ## Why both handlers, not just one - `Application.UnhandledException` does not fire for `Frame.NavigationFailed`. The Frame raises its own event first and, if no handler runs or `e.Handled` is left `false`, then it rethrows on the dispatcher. - Conversely, `Frame.NavigationFailed` only fires for navigation failures — not for an exception thrown directly in `OnLaunched` before any navigation happens. The two events are complementary, so both need a handler to fully cover the launch + navigation paths. ## Testing - The local NuGet feed on my dev box currently can't restore `Microsoft.NETCore.App.Runtime.win-x64 = 10.0.9` (the feed only has `11.0.0-preview.1.26104.118`), which fails the project restore for every WinUI project including this one. That's the same environment issue I called out on #48414 — pipeline restore uses a different feed and is fine. - All three patterns added here are copy-paste analogues of code that already exists in `Settings.UI` (`App.xaml.cs:96, 106-109`, `ShellViewModel.cs:86, 136`), so namespace and signature drift risk is minimal. The only behavioural difference is `e.Handled = true`, which is the actual goal of this PR. ## Risk - Low. Two new event handlers and one try/catch. No behaviour change on the success path. - Worst-case regression is that a real, repeatable XAML failure becomes silent in the runner's eyes (no process crash) instead of loud — but it's logged via `Logger.LogError` so the user can still find the trace in `%LOCALAPPDATA%\Microsoft\PowerToys\Logs\`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ADO: https://microsoft.visualstudio.com/DefaultCollection/OS/_workitems/edit/61258633/ --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>