Files
winutil/functions/private/Remove-WinUtilProvisionedAPPX.ps1
T
9791386f53 fix: resolve silent failures in AppX removal and PS7 DISM bugs (#4822)
* fix: resolve silent failures in AppX removal and PS7 DISM bugs

- Fixed a bug where Remove-AppxPackage failed silently in PowerShell 7 due to pipeline binding issues. We now explicitly loop through Get-AppxPackage results and pass PackageFullName directly.
- Added wildcard matching to Get-AppxPackage and Get-AppxProvisionedPackage to reliably locate packages regardless of short name vs family name variations.
- Offloaded Get-AppxProvisionedPackage and Remove-AppxProvisionedPackage execution to Windows PowerShell 5.1 (powershell.exe) to bypass PowerShell 7 DISM COM exceptions ("Class not registered") and performance hangs.
- Deduplicated AppX removal logic by calling Remove-WinUtilAPPX directly from Invoke-WPFAppxRemoval instead of copying the implementation.

* refactor(Remove-WinUtilAPPX): use script block to improve readability

* feat: enhance AppX removal process and add provisioned package removal function

* fix(tests): update AppX removal tests

This also adds tests for the new Remove-WinUtilProvisionedAPPX functionality

* Move AppX removal under Tweaks

* Address AppX removal review feedback

* Complete AppX removal error handling

* Prevent AppX cleanup confirmation prompts

---------

Co-authored-by: Chris Titus <contact@christitus.com>
2026-07-13 13:16:35 -05:00

62 lines
2.2 KiB
PowerShell

function Remove-WinUtilProvisionedAPPX {
<#
.SYNOPSIS
Removes all AppX provisioned packages that match the given names
.PARAMETER PackageList
An array of names of the APPX packages to remove
.EXAMPLE
Remove-WinUtilProvisionedAPPX -PackageList @("Microsoft.Microsoft3DViewer", "Microsoft.WindowsCalculator")
#>
param (
[string[]]$PackageList
)
if ($null -eq $PackageList -or $PackageList.Count -eq 0) {
return
}
Write-Host "`nRemoving provisioned packages..."
Write-WinUtilLog -Component "AppX" -Message "Removing AppX provisioned packages: $($PackageList -join ', ')"
# DISM cmdlets like Get-AppxProvisionedPackage often fail with "Class not registered" or hang in PowerShell 7.
# We shell out to Windows PowerShell 5.1 (powershell.exe) to reliably remove the provisioned packages.
$ps5Command = {
$pkgs = $args
$provisionedPackages = Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue
$failures = [System.Collections.Generic.List[string]]::new()
foreach ($Package in $pkgs) {
$provs = $provisionedPackages |
Where-Object DisplayName -Like "*$Package*"
if ($null -ne $provs) {
foreach ($prov in $provs) {
try {
Remove-AppxProvisionedPackage -Online -PackageName $prov.PackageName -ErrorAction Stop | Out-Null
}
catch {
$failures.Add("Failed to remove provisioned AppX package $($prov.PackageName): $($_.Exception.Message)")
}
}
}
}
if ($failures.Count -gt 0) {
throw ($failures -join [Environment]::NewLine)
}
}
$removalOutput = powershell.exe -NoProfile -NonInteractive -Command $ps5Command -args $PackageList 2>&1
if ($LASTEXITCODE -ne 0 -or $null -ne $removalOutput) {
$failureDetails = ($removalOutput | Out-String).Trim()
Write-WinUtilLog -Level "ERROR" -Component "AppX" -Message "AppX provisioned package removal failed: $failureDetails"
return
}
Write-WinUtilLog -Component "AppX" -Message "AppX provisioned package removal completed."
}