Keeping your software up to date using winget and PowerShell
winget
is a package manager for Windows. You can use winget install <package>
to install new software. You can also use winget upgrade <package>
or winget upgrade --all --silent
to upgrade one or all installed software. But what if you want to upgrade only a subset of your installed software? Or what if you want to schedule the upgrade to run every night? In this post, I describe how to use winget and PowerShell Core to keep your software up to date on a Windows machine.
There are multiple winget clients. You can use it using the winget.exe
or using PowerShell. The PowerShell flavor is the one I'm going to use in this post. The interesting point of PowerShell is that you can easily query installed packages and filter them out.
Before using winget from PowerShell, you must install it using the following command:
Install-Module -Name Microsoft.WinGet.Client
You can query all packages having an update available using the following command:
Get-WinGetPackage | Where-Object { $_.IsUpdateAvailable }
You can update all packages using:
Get-WinGetPackage | Where-Object { $_.IsUpdateAvailable } | Update-WinGetPackage
If you want to exclude specific packages from the update, you can use the following command:
Get-WinGetPackage `
| Where-Object { $_.IsUpdateAvailable } `
| Where-Object { $_.Id -notlike "TechSmith.*" } `
| Update-WinGetPackage
#Auto update using a scheduled task
Create a new file named
WingetUpdate.ps1
ps1 file:WingetUpdate.ps1 (PowerShell)Install-Module -Name Microsoft.WinGet.Client Get-WinGetPackage | Where-Object {$_.IsUpdateAvailable} | Where-Object {$_.Id -notlike "TechSmith*"} # You can filter out packages you don't want to update | Update-WinGetPackage
Create a new scheduled task using the following command:
PowerShell# Note: This script must be run as admin if "-RunLevel Highest" is present # TODO replace with the actual path to the script $ScriptPath=(Resolve-Path "WingetUpdate.ps1").Path $WinGet = "$env:LOCALAPPDATA\Microsoft\WindowsApps\winget.exe" $Pwsh = (Get-Command pwsh).Source $Time = New-ScheduledTaskTrigger -At 04:00 -Daily $Actions = @( # Update all sources, so that winget can find the latest version of the packages New-ScheduledTaskAction -Execute "$WinGet" -Argument "source update" New-ScheduledTaskAction -Execute "$Pwsh" -Argument "`"$ScriptPath`"}`"" ) $Settings = New-ScheduledTaskSettingsSet -WakeToRun:$false ` -MultipleInstances IgnoreNew ` -RunOnlyIfNetworkAvailable:$true ` -StartWhenAvailable:$true Register-ScheduledTask -TaskName "Update winget" -TaskPath Updates ` -Trigger $Time -Action $Actions -Settings $Settings ` -RunLevel Highest # Remove this one if you don't want to run the task as admin
You can open the Task Scheduler to see the new task. You can also run it manually to see if it works as expected.
Do you have a question or a suggestion about this post? Contact me!