Skip to content

Instantly share code, notes, and snippets.

@inxomnyaa
Last active November 25, 2024 17:46
Show Gist options
  • Save inxomnyaa/0ee29d68a6b4c92ba53810828dbc0f4a to your computer and use it in GitHub Desktop.
Save inxomnyaa/0ee29d68a6b4c92ba53810828dbc0f4a to your computer and use it in GitHub Desktop.
Upgrade Selected Apps via Winget
# Based on https://www.codewrecks.com/post/general/winget-update-selective/ (gist at https://gist.github.com/alkampfergit/2f662c07df0ca379c8e8e65e588c687b)
# Adds a grid for selecting multiple apps
# Fixes packages with truncated names
# Adds a confirmation dialogue before actually upgrading
class Software {
[string]$Name
[string]$Id
[string]$Version
[string]$AvailableVersion
}
function Winget-Query-Full-Id{
param(
[string]$string
)
$listLine = winget list $string.TrimEnd("…") | Out-String
$listLines = $listLine.Split([Environment]::NewLine)
For ($i = 0; $i -le $listLines.Length; $i++)
{
$sel = $listLines[$i] | Select-String -Pattern "($($string.TrimEnd("…"))\S*)"# -AllMatches
if (-not $sel) {
continue
}
return $sel.Matches[0].Value
}
return $string.TrimEnd("…")
}
$upgradeResult = winget upgrade --include-unknown | Out-String
$lines = $upgradeResult.Split([Environment]::NewLine)
# Find the line that starts with Name, it contains the header
$fl = 0
while (-not $lines[$fl].StartsWith("Name"))
{
$fl++
}
# Line $i has the header, we can find char where we find ID and Version
$idStart = $lines[$fl].IndexOf("Id")
$versionStart = $lines[$fl].IndexOf("Version")
$availableStart = $lines[$fl].IndexOf("Available")
$sourceStart = $lines[$fl].IndexOf("Source")
# Now cycle in real package and split accordingly
$upgradeList = @()
For ($i = $fl + 1; $i -le $lines.Length; $i++)
{
$line = $lines[$i]
if ($line.Length -gt ($availableStart + 1) -and -not $line.StartsWith('-'))
{
$name = $line.Substring(0, $idStart).TrimEnd()
$id = $line.Substring($idStart, $versionStart - $idStart).TrimEnd()
#Write-Host "$id"
if($line.IndexOf("…") -gt -1){
# Fix Id if it was truncated
$id = Winget-Query-Full-Id -string $id
}
$version = $line.Substring($versionStart, $availableStart - $versionStart).TrimEnd()
$available = $line.Substring($availableStart, $sourceStart - $availableStart).TrimEnd()
$software = [Software]::new()
$software.Name = $name;
$software.Id = $id;
$software.Version = $version
$software.AvailableVersion = $available;
$upgradeList += $software
}
}
$upgradeList | Format-Table
$toUpgrade = $upgradeList | Out-GridView -PassThru
$upgraded = 0
foreach ($package in $toUpgrade)
{
# TODO add option to skip this dialogue
$title = "Upgrade $($package.id)?"
$question = "Upgrade package $($package.id) from $($package.version) to $($package.availableversion)?"
$choices = '&Yes', '&No'
$decision = $Host.UI.PromptForChoice($title, $question, $choices, 0)
if ($decision -eq 0) {
Write-Host "Going to upgrade package $($package.id)"
# TODO add option to skip waiting for input
& winget upgrade --include-unknown --wait --verbose $package.id
if($?){
Write-Host "Success"
$script:upgraded++
}
else{
Write-Host "Failed"
}
}
else {
Write-Host "Skipped upgrade to package $($package.id)"
}
}
Write-Host "Upgraded $($upgraded) out of $($package.Count)"
Read-Host -Prompt "Press any key to exit"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment