CmdPal: Harden performance monitor and enable crash recovery (#46541)

<!-- 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

This PR has two parts:

1. Hardens the managed paths in the Performance Monitor extension to
catch everything we can.
1. Adds crash recovery for cases where something fails in a way we
cannot handle.

## Pictures? Pictures!

<img width="1060" height="591" alt="image"
src="https://github.com/user-attachments/assets/ee91c610-32eb-4117-b9b8-6bbc40b9b426"
/>


<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #46522
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Jiří Polášek
2026-03-28 00:39:26 +01:00
committed by GitHub
parent f686155d9b
commit 943c2a1ff5
15 changed files with 1338 additions and 184 deletions

View File

@@ -125,7 +125,7 @@ public partial class App : Application, IDisposable
services.AddSingleton(TaskScheduler.FromCurrentSynchronizationContext());
var dispatcherQueue = DispatcherQueue.GetForCurrentThread();
AddBuiltInCommands(services);
AddBuiltInCommands(services, appInfoService.ConfigDirectory);
AddCoreServices(services, appInfoService);
@@ -134,8 +134,10 @@ public partial class App : Application, IDisposable
return services.BuildServiceProvider();
}
private static void AddBuiltInCommands(ServiceCollection services)
private static void AddBuiltInCommands(ServiceCollection services, string configDirectory)
{
var providerLoadGuard = new ProviderLoadGuard(configDirectory);
// Built-in Commands. Order matters - this is the order they'll be presented by default.
var allApps = new AllAppsCommandProvider();
var files = new IndexerCommandsProvider();
@@ -166,8 +168,7 @@ public partial class App : Application, IDisposable
}
catch (Exception ex)
{
Logger.LogError("Couldn't load winget");
Logger.LogError(ex.ToString());
Logger.LogError("Couldn't load winget", ex);
}
services.AddSingleton<ICommandProvider, WindowsTerminalCommandsProvider>();
@@ -178,7 +179,37 @@ public partial class App : Application, IDisposable
services.AddSingleton<ICommandProvider, TimeDateCommandsProvider>();
services.AddSingleton<ICommandProvider, SystemCommandExtensionProvider>();
services.AddSingleton<ICommandProvider, RemoteDesktopCommandProvider>();
services.AddSingleton<ICommandProvider, PerformanceMonitorCommandsProvider>();
var performanceMonitorSoftDisabled = providerLoadGuard.IsProviderDisabled(PerformanceMonitorCommandsProvider.ProviderIdValue);
if (performanceMonitorSoftDisabled)
{
Logger.LogWarning("Performance monitor is temporarily disabled after repeated crashes. Loading placeholder pages instead of activating performance counters.");
}
if (!performanceMonitorSoftDisabled)
{
providerLoadGuard.Enter(PerformanceMonitorCommandsProvider.ProviderLoadGuardBlockId, PerformanceMonitorCommandsProvider.ProviderIdValue);
}
try
{
var performanceMonitor = new PerformanceMonitorCommandsProvider(performanceMonitorSoftDisabled);
services.AddSingleton<ICommandProvider>(performanceMonitor);
if (!performanceMonitorSoftDisabled)
{
providerLoadGuard.Exit(PerformanceMonitorCommandsProvider.ProviderLoadGuardBlockId);
}
}
catch (Exception ex)
{
if (!performanceMonitorSoftDisabled)
{
providerLoadGuard.Exit(PerformanceMonitorCommandsProvider.ProviderLoadGuardBlockId);
}
Logger.LogError("Couldn't load performance monitor", ex);
}
}
private static void AddUIServices(ServiceCollection services, DispatcherQueue dispatcherQueue)