Note: Run As Administrator
# winget needs an elevated session to upgrade machine-scoped packages.
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
throw "This script must be run as Administrator."
}
# Log stdout/stderr separately so a failed upgrade is easy to diagnose after the fact.
$logPath = Join-Path $env:TEMP 'winget-upgrade-all.log'
$errorPath = Join-Path $env:TEMP 'winget-upgrade-all-error.log'
$timeoutMs = [int][TimeSpan]::FromMinutes(30).TotalMilliseconds
# Upgrade everything winget knows about, without any prompts.
$arguments = @(
'upgrade'
'--all'
'--silent'
'--accept-package-agreements'
'--accept-source-agreements'
'--include-unknown'
'--disable-interactivity'
)
$process = Start-Process -FilePath 'winget.exe' `
-ArgumentList $arguments `
-NoNewWindow `
-PassThru `
-RedirectStandardOutput $logPath `
-RedirectStandardError $errorPath
try {
if (-not $process.WaitForExit($timeoutMs)) {
# Kill winget and any installer processes it launched.
& taskkill.exe /PID $process.Id /T /F *> $null
$process.WaitForExit()
throw "winget exceeded the 30-minute timeout and was terminated."
}
$exitCode = $process.ExitCode
# Return a summary object instead of raw exit code so callers can log/branch on it.
[pscustomobject]@{
ExitCode = $exitCode
Succeeded = ($exitCode -eq 0)
OutputLog = $logPath
ErrorLog = $errorPath
}
}
finally {
$process.Dispose()
}