From 1106ac61f51abfa35d4c77280efb4884cc8e0c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Wed, 25 Mar 2026 18:12:11 +0100 Subject: [PATCH] CmdPal: Guard Frame.GoBack to prevent crash (#46493) ## Summary of the Pull Request This PR adds a guard to the shell page that prevents navigating back with empty nav stack (which leads to exception, an ultimately to a crash). > You should check that the [CanGoBack](https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.frame.cangoback?view=windows-app-sdk-1.8#microsoft-ui-xaml-controls-frame-cangoback) property is true before you call GoBack. If you call GoBack while CanGoBack is false, an exception is thrown. ## PR Checklist - [x] Closes: #46492 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --- .../Pages/ShellPage.xaml.cs | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs index 6a33569ec0..6d67743f0b 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs @@ -26,7 +26,6 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Media.Animation; -using Windows.UI.Core; using WinUIEx; using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue; using VirtualKey = Windows.System.VirtualKey; @@ -485,20 +484,23 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, // However, then we have more fine-grained control on the back stack, managing the VM cache, and not // having that all be a black box, though then we wouldn't cache the XAML page itself, but sometimes that is a drawback. // However, we do a good job here, see ForwardStack.Clear below, and BackStack.Clear above about managing that. - if (withAnimation) + if (RootFrame.CanGoBack) { - RootFrame.GoBack(); - } - else - { - RootFrame.GoBack(_noAnimation); - } + if (withAnimation) + { + RootFrame.GoBack(); + } + else + { + RootFrame.GoBack(_noAnimation); + } - // Don't store pages we're navigating away from in the Frame cache - // TODO: In the future we probably want a short cache (3-5?) of recent VMs in case the user re-navigates - // back to a recent page they visited (like the Pokedex) so we don't have to reload it from scratch. - // That'd be retrieved as we re-navigate in the PerformCommandMessage logic above - RootFrame.ForwardStack.Clear(); + // Don't store pages we're navigating away from in the Frame cache + // TODO: In the future we probably want a short cache (3-5?) of recent VMs in case the user re-navigates + // back to a recent page they visited (like the Pokedex) so we don't have to reload it from scratch. + // That'd be retrieved as we re-navigate in the PerformCommandMessage logic above + RootFrame.ForwardStack.Clear(); + } if (!RootFrame.CanGoBack) {