mirror of
https://github.com/Raphire/Win11Debloat.git
synced 2026-07-03 07:08:27 +00:00
* remove support for uninstalling old sunset apps * Add color legend on app removal screen * Remove legacy app list generator and custom apps file support Replaced by GUI config export/import, dynamic RemovalMethod, and CLI app removal settings saved to LastUsedSettings.json. * Verify app removal by checking actual installation state instead of trusting winget output
110 lines
3.3 KiB
PowerShell
110 lines
3.3 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Returns a list of installed apps from winget as structured objects.
|
|
|
|
.DESCRIPTION
|
|
Runs `winget list` and parses the output into PSCustomObject arrays.
|
|
Use -NonBlocking to keep the UI responsive in GUI mode; otherwise
|
|
runs synchronously with an optional timeout.
|
|
|
|
.PARAMETER TimeOut
|
|
Maximum seconds to wait for winget to complete. Default is 10.
|
|
|
|
.PARAMETER NonBlocking
|
|
When set, runs via Invoke-NonBlocking so the GUI thread stays responsive.
|
|
|
|
.OUTPUTS
|
|
PSCustomObject[] with Name and Id properties. Returns $null on
|
|
failure, or an empty array when winget succeeds but lists no apps.
|
|
#>
|
|
function GetInstalledAppsViaWinget {
|
|
param (
|
|
[int]$TimeOut = 10,
|
|
[switch]$NonBlocking
|
|
)
|
|
|
|
if (-not $script:WingetInstalled) { return $null }
|
|
|
|
$fetchBlock = {
|
|
param($timeOut)
|
|
$job = Start-Job {
|
|
$rawOutput = $null
|
|
try {
|
|
$originalEncoding = [Console]::OutputEncoding
|
|
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
|
|
try {
|
|
$rawOutput = winget list --accept-source-agreements --disable-interactivity
|
|
}
|
|
finally {
|
|
[Console]::OutputEncoding = $originalEncoding
|
|
}
|
|
return $rawOutput
|
|
}
|
|
catch {
|
|
return $null
|
|
}
|
|
}
|
|
|
|
$done = $job | Wait-Job -Timeout $timeOut
|
|
if ($done) {
|
|
$result = Receive-Job -Job $job
|
|
Remove-Job -Job $job -ErrorAction SilentlyContinue
|
|
|
|
if (-not $result) { return $null }
|
|
|
|
# winget list outputs:
|
|
# [progress line] / [blank] / header / --- separator / data rows
|
|
$textOutput = $result -join "`n"
|
|
$lines = $textOutput -split "`r`n|`n"
|
|
|
|
# Find the separator line to know where data starts
|
|
$dataStart = -1
|
|
for ($i = 0; $i -lt $lines.Count; $i++) {
|
|
if ($lines[$i] -match '^-{3,}') {
|
|
$dataStart = $i + 1
|
|
break
|
|
}
|
|
}
|
|
|
|
if ($dataStart -lt 0 -or $dataStart -ge $lines.Count) { return @() }
|
|
|
|
$apps = [System.Collections.Generic.List[object]]::new()
|
|
|
|
for ($i = $dataStart; $i -lt $lines.Count; $i++) {
|
|
$line = $lines[$i]
|
|
if ($line.Trim() -eq '') { continue }
|
|
|
|
try {
|
|
# Split on 2+ spaces; extract Name and Id columns.
|
|
$fields = [regex]::Split($line.Trim(), '\s{2,}')
|
|
if ($fields.Count -lt 2) { continue }
|
|
|
|
$name = $fields[0].Trim()
|
|
$id = $fields[1].Trim()
|
|
|
|
if (-not $id) { continue }
|
|
|
|
$null = $apps.Add([PSCustomObject]@{
|
|
Name = $name
|
|
Id = $id
|
|
})
|
|
}
|
|
catch {
|
|
# Skip lines that can't be parsed
|
|
}
|
|
}
|
|
|
|
return @($apps)
|
|
}
|
|
|
|
Remove-Job -Job $job -Force -ErrorAction SilentlyContinue
|
|
return $null
|
|
}
|
|
|
|
if ($NonBlocking) {
|
|
return Invoke-NonBlocking -ScriptBlock $fetchBlock -ArgumentList $TimeOut
|
|
}
|
|
else {
|
|
return & $fetchBlock $TimeOut
|
|
}
|
|
} |