CmdPal: Hide uninstall option for system apps#48104
Draft
michaeljolley wants to merge 13 commits into
Draft
Conversation
System-signed UWP packages (Settings, Task Manager, Registry Editor) should not show an uninstall option in the context menu. Add IsNonRemovable property threaded from Windows.ApplicationModel.Package .SignatureKind through PackageWrapper -> IPackage -> UWP, and gate the UninstallApplicationConfirmation behind !Package.IsNonRemovable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#46826) The previous commit guarded UWP system packages via Package.IsNonRemovable. This commit extends protection to Win32/.lnk-based system utilities (Control Panel, Task Manager, Registry Editor, etc.) by checking whether the resolved executable path lives under System32, SysWOW64, or SystemApps. Path-based detection was chosen over registry SystemComponent lookups because the FullPath is already resolved during program discovery (no additional I/O), and system executables reliably reside in these well-known OS directories. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
FullPath for .lnk shortcuts can still point to the shortcut file itself (e.g., C:\ProgramData\...\Task Manager.lnk) rather than the resolved target executable. GetAppIdentifier() reliably encodes the actual executable path after the pipe delimiter (Name|ExePath). Extract the resolved path via GetResolvedExecutablePath() before running the system directory check. This ensures Task Manager, Control Panel, and other System32 targets are correctly identified as protected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The check-spelling bot flagged lowercase 'uninstaller' as unrecognized. The expect list had 'Uninstaller' (capitalized) but our code comments use the lowercase form. Added both lowercase variants. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ist" This reverts commit e7f8e2f.
…list" This reverts commit 3ace942.
FullPath for .lnk shortcuts can still point to the shortcut file itself (e.g., C:\ProgramData\...\Task Manager.lnk) rather than the resolved target executable. GetAppIdentifier() reliably encodes the actual executable path after the pipe delimiter (Name|ExePath). Extract the resolved path via GetResolvedExecutablePath() before running the system directory check. This ensures Task Manager, Control Panel, and other System32 targets are correctly identified as protected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…b.com/microsoft/PowerToys into dev/mjolley/fix-uninstall-system-apps
LegendaryBlair
added a commit
that referenced
this pull request
May 25, 2026
## Problem Since #47119 (`Refresh check-spelling 0.0.26`, merged 2026-04-23) refreshed the check-spelling tooling and rewrote `.github/actions/spell-check/expect.txt` (938 lines / 633 deletions), the check-spelling bot has been leaving a noisy advisory comment on **every PR**: > #### These words are not needed and should be removed > ABlocked AClient AColumn ACR ADate ADifferent AHybrid ALarger AModifier ANull AOklab APeriod ARandom ARemapped ASingle ASUS bck … The same ~150-word list is appended verbatim to every PR the bot looks at (verified against #48058, #48102, #48104 — the list is identical). These tokens are residual orphans in `expect.txt` from before the 0.0.26 refresh and no longer match anything in source. ## Fix Removes exactly the 147 orphan tokens that the bot has consistently flagged as `now absent` from `.github/actions/spell-check/expect.txt`. The removed tokens are exclusively the ones the bot itself identified. All uppercase Win32 / DirectWrite identifiers that are still used in source (`DWRITE`, `LWIN`, `VCENTER`, `VREDRAW`, etc.) are **preserved**. ## Verification - Diff is a single file, deletions only: `expect.txt` shrinks from 2343 → 2196 lines. - Each of the 4 uppercase Win32 tokens (`DWRITE` line 514, `LWIN` 1074, `VCENTER` 2105, `VREDRAW` 2144 in the original) remains in the file. - The check-spelling job on this PR should now post a clean report (no `should be removed` block). ## Background — which PR introduced the drift | PR | Date | What it changed | |----|------|-----------------| | **#47119** | 2026-04-23 | Refreshed check-spelling to 0.0.26; rewrote `expect.txt` with 938 line-changes (633 deletions, 305 additions). The duplicated lowercase/uppercase entries and many obsolete tokens originate here. | --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <Copilot@users.noreply.github.com>
…6826) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ly (#46826) LnkProgram() already resolves FullPath to the shortcut target executable before storing the Win32Program record. GetResolvedExecutablePath() was parsing GetAppIdentifier() (which is 'Name|FullPath') and extracting FullPath right back out — a circular no-op with incorrect doc comments. Remove the helper and have IsProtectedSystemApp() read FullPath directly, with updated comments explaining why FullPath is already resolved. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #46826
The CmdPal "Uninstall" context menu command was shown for system/framework apps that cannot or should not be uninstalled (Control Panel, Task Manager, Registry Editor, Settings, etc.).
Root Cause
Two separate code paths add the Uninstall command:
UWPApplication.GetCommands()had no guardWin32Program.GetCommands()had no guardFix
UWP Path
Added
IsNonRemovableproperty toIPackage→PackageWrapper→UWP, derived fromPackage.SignatureKind == PackageSignatureKind.System. The uninstall command is gated behind!Package.IsNonRemovable.Win32/.lnk Path
Added
IsProtectedSystemApp()which checks whether the resolved executable path lives under:%SystemRoot%\System32— core OS binaries%SystemRoot%\SysWOW64— 32-bit system binaries%SystemRoot%\SystemApps— inbox Windows Store appsPath-based detection was chosen over registry
SystemComponentlookups because:%ProgramFiles%\WindowsAppsis intentionally NOT blocked — Win11 optional features (Notepad, Paint) live there and have valid uninstallers.Changes
IPackage.cs: Addedbool IsNonRemovablepropertyPackageWrapper.cs: ImplementsIsNonRemovablefromSignatureKind == SystemUWP.cs: ThreadsIsNonRemovablethroughUWPApplication.cs: Gates uninstall behind!Package.IsNonRemovableWin32Program.cs: AddedIsProtectedSystemApp()and gates uninstall behind it