mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2026-08-10 10:01:16 +10:00
* Make UI helpers no-op when no window exists The -Preset and -Config paths run Invoke-WinUtilAutoRun before the XAML form is created and before PresentationCore is loaded, so every call into Invoke-WPFUIThread failed with InvokeMethodOnNull and every call into Set-WinUtilTweaksProgressIndicator failed to resolve [Windows.Visibility]. The errors were non-terminating, so tweaks still applied, but each run filled the log with noise. Loading presentationframework earlier does not help: Visibility lives in PresentationCore, which only loads once a WPF object is instantiated, and the XAML-named progress controls do not exist in these paths either. Guarding the two helpers covers Invoke-WPFtweaksbutton, Invoke-WPFundoall and Invoke-WPFFeatureInstall, which the existing per-call-site $hasUI convention never reached. * Suppress stray console output from automation runs Invoke-WPFRunspace returns an IAsyncResult that no caller uses, and Set-WinUtilRegistry was the only New-PSDrive call site that did not suppress its output. A GUI click handler discards both, but the -Preset and -Config paths call the workflows directly, so an async handle dump and a PSDrive table landed in the user's log. The handle itself is kept because pester/runspace.Tests.ps1 asserts that Invoke-WPFRunspace returns a single IAsyncResult, so the suppression goes at the four call sites reachable from Invoke-WinUtilAutoRun. * Add project learning for window-free UI helpers
101 lines
5.0 KiB
PowerShell
101 lines
5.0 KiB
PowerShell
function Invoke-WPFAppxRemoval {
|
|
if ($sync.ProcessRunning) {
|
|
Show-WinUtilMessage -Message "An AppX process is currently running." -Title "WinUtil" -Button "OK" -Icon "Warning"
|
|
return
|
|
}
|
|
|
|
if ($null -eq $sync.selectedAppx -or $sync.selectedAppx.Count -eq 0) {
|
|
Show-WinUtilMessage -Message "No AppX Package selected" -Title "Error" -Button "OK" -Icon "Error"
|
|
return
|
|
}
|
|
|
|
$selected = @($sync.selectedAppx)
|
|
$apps = $sync.configs.appxHashtable
|
|
|
|
$sync.ProcessRunning = $true
|
|
Invoke-WPFRunspace -ParameterList @(("selected", $selected), ("apps", $apps)) -ScriptBlock {
|
|
param($selected, $apps)
|
|
|
|
$totalPackages = @($selected).Count
|
|
$hasUI = $null -ne $sync.Form -and $null -ne $sync.Form.Dispatcher
|
|
$packageList = [System.Collections.Generic.List[string]]::new()
|
|
|
|
try {
|
|
Write-WinUtilLog -Component "AppX" -Message "Starting AppX removal for $totalPackages selected package(s)."
|
|
if ($hasUI) {
|
|
Set-WinUtilTweaksProgressIndicator -Visible $true -Label "Preparing AppX removal (0/$totalPackages)" -Percent 0
|
|
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }
|
|
}
|
|
|
|
for ($index = 0; $index -lt $totalPackages; $index++) {
|
|
$key = $selected[$index]
|
|
$app = $apps[$key]
|
|
$position = $index + 1
|
|
$startPercent = [int](($index / $totalPackages) * 90)
|
|
if ($hasUI) {
|
|
Set-WinUtilTweaksProgressIndicator -Visible $true -Label "Removing $($app.Content) ($position/$totalPackages)" -Percent $startPercent
|
|
}
|
|
|
|
if ($key -eq "WPFAppxMicrosoft_XboxGamingOverlay") {
|
|
# Making sure Game Bar isn't running
|
|
Write-WinUtilLog -Component "AppX" -Message "Stopping GameBarFTServer before removing Xbox Gaming Overlay."
|
|
Stop-Process -Name GameBarFTServer -Force -Confirm:$false -ErrorAction SilentlyContinue
|
|
|
|
# This stops annoying ms-gamebar popup when launching games.
|
|
Write-WinUtilLog -Component "AppX" -Message "Disabling Game DVR capture before removing Xbox Gaming Overlay."
|
|
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\GameDVR -Name AppCaptureEnabled -Value 0
|
|
}
|
|
|
|
if ($key -eq "WPFAppxMicrosoft_WindowsNotepad") {
|
|
Write-WinUtilLog -Component "AppX" -Message "Stopping dllhost before removing Notepad."
|
|
Stop-Process -Name dllhost -Force -Confirm:$false -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
Write-Host "Removing $($app.Content)"
|
|
Write-WinUtilLog -Component "AppX" -Message "Removing $($app.Content) ($($app.PackageId))."
|
|
Remove-WinUtilAPPX -Name $app.PackageId
|
|
$packageList.Add($app.PackageId)
|
|
|
|
if ($key -eq "WPFAppxMSTeams") {
|
|
# Uninstalls Microsoft Teams Meeting Add-in for Microsoft Office
|
|
Write-WinUtilLog -Component "AppX" -Message "Uninstalling Microsoft Teams meeting add-in package."
|
|
Get-Package -Name "Microsoft Teams*" -ErrorAction SilentlyContinue | Uninstall-Package -Force
|
|
}
|
|
|
|
$completedPercent = [int](($position / $totalPackages) * 90)
|
|
if ($hasUI) {
|
|
Set-WinUtilTweaksProgressIndicator -Visible $true -Label "Removed $($app.Content) ($position/$totalPackages)" -Percent $completedPercent
|
|
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($completedPercent / 100) }
|
|
}
|
|
}
|
|
|
|
if ($packageList.Count -gt 0) {
|
|
if ($hasUI) {
|
|
Set-WinUtilTweaksProgressIndicator -Visible $true -Label "Removing provisioned AppX packages" -Percent 90
|
|
}
|
|
Remove-WinUtilProvisionedAPPX -PackageList $packageList.ToArray()
|
|
}
|
|
|
|
Write-Host "================================="
|
|
Write-Host "-- AppX Removal Finished ---"
|
|
Write-Host "================================="
|
|
Write-WinUtilLog -Component "AppX" -Message "AppX removal finished."
|
|
if ($hasUI) {
|
|
Set-WinUtilTweaksProgressIndicator -Visible $true -Label "AppX removal finished" -Percent 100
|
|
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
|
|
}
|
|
}
|
|
catch {
|
|
Write-WinUtilLog -Level "ERROR" -Component "AppX" -Message "AppX removal failed: $($_.Exception.Message)"
|
|
if ($hasUI) {
|
|
Set-WinUtilTweaksProgressIndicator -Visible $true -Label "AppX removal failed" -Percent 100
|
|
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" -overlay "warning" }
|
|
}
|
|
}
|
|
finally {
|
|
$sync.ProcessRunning = $false
|
|
}
|
|
|
|
} | Out-Null
|
|
}
|