Public/Start-WingetUpdateCheck.ps1
|
function Start-WingetUpdateCheck { <# .SYNOPSIS Checks for winget updates in the background. .DESCRIPTION This command is typically triggered by your PowerShell profile if you've enabled update notifications via Enable-WingetUpdateNotifications. It runs winget upgrade in a background job and pops a native Windows toast notification if any updates are found. It respects the interval set in the configuration. .PARAMETER Force Ignore the configured check interval and check immediately. #> [CmdletBinding()] param( [switch]$Force ) $configDir = Get-WingetBatchConfigDir $configFile = Join-Path $configDir "config.json" if (-not (Test-Path $configFile)) { return } $config = Get-Content $configFile -Raw | ConvertFrom-Json if (-not $config.UpdateNotificationsEnabled) { return } if (-not $Force) { if ($config.LastCheck) { try { $lastCheckTime = [datetime]$config.LastCheck $interval = $config.CheckInterval if ($interval -gt 0 -and (Get-Date) -lt $lastCheckTime.AddHours($interval)) { return } } catch { # Invalid date format, just proceed } } elseif (-not $config.CheckOnStartup) { # No LastCheck, but CheckOnStartup is false. $config.LastCheck = (Get-Date).ToString("o") $config | ConvertTo-Json | Out-File -FilePath $configFile -Encoding UTF8 -Force return } } # Update LastCheck immediately to prevent multiple rapid checks from multiple terminal sessions $config.LastCheck = (Get-Date).ToString("o") $config | ConvertTo-Json | Out-File -FilePath $configFile -Encoding UTF8 -Force $jobScript = { try { $updates = winget upgrade 2>&1 $updateCount = 0 $packages = @() foreach ($line in $updates) { if ($line -match '^\s*[a-zA-Z]') { # Filter out headers, empty lines, and non-package winget outputs if ($line -notmatch 'Name\s+|Id\s+|Version\s+|Available\s+|Source\s+|-{5,}|No installed package found|Failed in attempting to update|upgrades available') { $updateCount++ if ($packages.Count -lt 3) { $parts = $line -split '\s{2,}' if ($parts.Count -gt 0) { $packages += $parts[0].Trim() } } } } } if ($updateCount -gt 0) { $pkgText = $packages -join ", " if ($updateCount -gt 3) { $pkgText += " and $($updateCount - 3) more" } Add-Type -AssemblyName System.Windows.Forms $balloon = New-Object System.Windows.Forms.NotifyIcon $path = (Get-Process -id $pid).Path $balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path) $balloon.BalloonTipIcon = "Info" $balloon.BalloonTipTitle = "Winget Updates Available ($updateCount)" $balloon.BalloonTipText = "Updates available for: $pkgText.`nRun 'Invoke-WinGetBatch' to install." $balloon.Visible = $true $balloon.ShowBalloonTip(10000) Start-Sleep -Seconds 10 $balloon.Dispose() } } catch { # Ignore background job errors so it fails silently in profile } } # Start the check in a background job so it doesn't block the user's terminal startup Start-Job -ScriptBlock $jobScript -Name "WingetUpdateCheck" | Out-Null } |