fix: honor cancellation during changes (#700)

Co-authored-by: Jeffrey <9938813+Raphire@users.noreply.github.com>
This commit is contained in:
Kushida
2026-07-14 22:06:40 +02:00
committed by GitHub
co-authored by Jeffrey
parent 8fa1332ff0
commit de817399e6
3 changed files with 37 additions and 81 deletions
+28 -80
View File
@@ -5,11 +5,10 @@
.DESCRIPTION
Iterates over the provided list of app identifiers and removes each one.
The removal method (winget vs. Appx cmdlets) is determined per-app from
Apps.json. Microsoft Edge is deferred to the end of the loop so that all
winget attempts run before any force-remove prompt. A scheduled task is
only created when the User or Sysprep parameter was passed.
After each winget removal, the system is checked to confirm whether the
app is still installed before reporting an error.
Apps.json. A scheduled task is only created when the User or Sysprep
parameter was passed. After winget removal, the system is checked to
confirm whether the app is still installed before reporting an error.
Returns early if the CancelRequested flag is set.
.PARAMETER appsList
An array of app package identifiers to remove (e.g. 'Microsoft.BingNews').
@@ -39,7 +38,6 @@ function RemoveApps {
$appIndex = 0
$edgeIds = @('Microsoft.Edge', 'XPFFTQ037JWMHS')
$edgeAppsInList = @()
$wingetRemovedApps = @()
Foreach ($app in $appsList) {
@@ -51,12 +49,6 @@ function RemoveApps {
& $script:ApplySubStepCallback "Removing apps ($appIndex/$appCount)" $appIndex $appCount
}
# Microsoft Edge is handled after the loop to avoid duplicate scheduled tasks and allow fallback if winget fails
if ($edgeIds -contains $app) {
$edgeAppsInList += $app
continue
}
Write-Host "Removing $app"
if ((Get-AppRemovalMethod $app) -eq 'WinGet') {
@@ -68,32 +60,32 @@ function RemoveApps {
}
}
# Remove Microsoft Edge
if ($edgeAppsInList.Count -gt 0) {
Remove-EdgeApp -edgeAppsInList $edgeAppsInList
if ($script:CancelRequested) {
Write-Host ""
return
}
# Check whether any winget-removed apps are still present, and report errors for each one.
if ($wingetRemovedApps.Count -gt 0 -or $edgeAppsInList.Count -gt 0) {
if ($wingetRemovedApps.Count -gt 0) {
$postRemovalList = if ($script:WingetInstalled) { GetInstalledAppsViaWinget -TimeOut 10 -NonBlocking } else { $null }
$edgeForceRemoveRequested = $false
foreach ($app in $wingetRemovedApps) {
if (Test-AppStillInstalled -appId $app -InstalledList $postRemovalList) {
if (-not (Test-AppStillInstalled -appId $app -InstalledList $postRemovalList)) {
continue
}
if ($edgeIds -contains $app) {
Write-Host "Unable to uninstall Microsoft Edge via WinGet" -ForegroundColor Red
if (-not $edgeForceRemoveRequested) {
Request-EdgeForceRemove
$edgeForceRemoveRequested = $true
}
}
else {
Write-Host "Unable to uninstall $app via WinGet" -ForegroundColor Red
}
}
# Verify Edge separately (triggers its own force-remove path if still installed)
$edgeStillInstalled = $false
foreach ($edgeApp in $edgeAppsInList) {
if (Test-AppStillInstalled -appId $edgeApp -InstalledList $postRemovalList) {
$edgeStillInstalled = $true
break
}
}
if ($edgeStillInstalled) {
Write-Host "Unable to uninstall Microsoft Edge via WinGet" -ForegroundColor Red
Request-EdgeForceRemove
}
}
Write-Host ""
@@ -101,15 +93,11 @@ function RemoveApps {
<#
.SYNOPSIS
Uninstalls a non-Edge app via WinGet and/or schedules its removal.
Uninstalls an app via WinGet and/or schedules its removal.
.DESCRIPTION
Runs winget uninstall for a single app. If the User or Sysprep
parameter was passed, also schedules removal for future logins.
After uninstall, the system is checked to confirm whether the app
is still present — winget output is not trusted on its
own, as it sometimes reports failure after a successful removal.
Edge apps are handled separately after the main loop.
.PARAMETER app
The WinGet package ID to uninstall (e.g. 'Microsoft.BingNews').
@@ -122,6 +110,11 @@ function Remove-WinGetApp {
return
}
Invoke-NonBlocking -ScriptBlock {
param($appId)
winget uninstall --accept-source-agreements --disable-interactivity --id $appId
} -ArgumentList $app
if ($script:Params.ContainsKey("User")) {
Write-Host "Adding scheduled task to uninstall $app for user $(GetUserName)..."
Set-RunOnceWingetTask -appId $app
@@ -130,51 +123,6 @@ function Remove-WinGetApp {
Write-Host "Adding scheduled task to uninstall $app for new users..."
Set-RunOnceWingetTask -appId $app
}
Invoke-NonBlocking -ScriptBlock {
param($appId)
winget uninstall --accept-source-agreements --disable-interactivity --id $appId
} -ArgumentList $app
}
<#
.SYNOPSIS
Removes Microsoft Edge via WinGet (both AppIds), with fallback to force-remove.
.DESCRIPTION
Edge has multiple package IDs. Runs winget uninstall for each one,
then creates a single scheduled task if the User or Sysprep parameter
was passed. After all attempts, the system is checked to confirm
whether Edge is still present. The force-remove prompt only
appears if Edge remains installed — winget false positives are ignored.
.PARAMETER edgeAppsInList
The Edge AppIds that appear in the removal list (one or both).
#>
function Remove-EdgeApp {
param([string[]]$edgeAppsInList)
if (-not $script:WingetInstalled) {
Write-Host "ERROR: WinGet is either not installed or is outdated, Microsoft Edge could not be removed" -ForegroundColor Red
return
}
if ($script:Params.ContainsKey("User")) {
Write-Host "Adding scheduled task to uninstall Microsoft Edge for user $(GetUserName)..."
Set-RunOnceWingetTask -appId 'Microsoft.Edge'
}
elseif ($script:Params.ContainsKey("Sysprep")) {
Write-Host "Adding scheduled task to uninstall Microsoft Edge for new users..."
Set-RunOnceWingetTask -appId 'Microsoft.Edge'
}
foreach ($edgeApp in $edgeAppsInList) {
Write-Host "Removing $edgeApp"
Invoke-NonBlocking -ScriptBlock {
param($appId)
winget uninstall --accept-source-agreements --disable-interactivity --id $appId
} -ArgumentList $edgeApp
}
}
<#
@@ -40,6 +40,8 @@ function Disable-TelemetryScheduledTasks {
$tasks = Get-TelemetryScheduledTasks
foreach ($task in $tasks) {
if ($script:CancelRequested) { return }
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Disable Scheduled Task: $($task.Path)$($task.Name)" -ForegroundColor Cyan
continue
@@ -92,6 +94,8 @@ function Enable-TelemetryScheduledTasks {
$tasks = Get-TelemetryScheduledTasks
foreach ($task in $tasks) {
if ($script:CancelRequested) { return }
if ($script:Params.ContainsKey("WhatIf")) {
Write-Host "[WhatIf] Enable Scheduled Task: $($task.Path)$($task.Name)" -ForegroundColor Cyan
continue
+4
View File
@@ -563,6 +563,10 @@ if (($controlParamsCount -eq $script:Params.Keys.Count) -or ($script:Params.Keys
# (This also handles restore point creation if requested)
Invoke-AllChanges
if ($script:CancelRequested) {
Write-Warning "Script execution was cancelled by the user. Any remaining changes were not applied."
AwaitKeyToExit
}
# Restart Explorer process unless running in Sysprep or User context
if (-not ($script:Params.ContainsKey("Sysprep") -or $script:Params.ContainsKey("User"))) {