Skip to content

Instantly share code, notes, and snippets.

@arpan3t
Created September 10, 2024 16:55
Show Gist options
  • Select an option

  • Save arpan3t/383f9b8af3df972d8ee0ebbc60e864d5 to your computer and use it in GitHub Desktop.

Select an option

Save arpan3t/383f9b8af3df972d8ee0ebbc60e864d5 to your computer and use it in GitHub Desktop.
PowerShell update checker that checks WinGet manifest before showing notification
# Current pwsh update notification code triggers notification on new release published to PowerShell repo.
# WinGet manifest is being updated manually (up to 3 days) after new releases, resulting in premature update notifications.
# This is a temporary solution until PowerShell adds WinGet manifest update to it's CI/CD pipeline.
# Add snippet to profile. To revert back - change psupdate check env variable to Default and remove snippet from profile.
# More info can be found at the following links:
# about_Update_Notifications - https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_update_notifications?view=powershell-7.4
# Update notification code - https://github.com/PowerShell/PowerShell/blob/master/src/Microsoft.PowerShell.ConsoleHost/host/msh/UpdatesNotification.cs
# CI/CD pipeline issue - https://github.com/PowerShell/PowerShell/issues/19927#issuecomment-2278451507
# Banner replacement issue - https://github.com/PowerShell/PowerShell/issues/20474#issuecomment-1769364740
# NOTE: Only for stable release (not LTS or preview) and requires WinGet PowerShell module!
$StableBuildUri = "https://aka.ms/pwsh-buildinfo-stable"
$CurrentVersion = $PSVersionTable.PSVersion
$CurrentDateTime = Get-Date
$CheckInterval = New-TimeSpan -Days 1
# Decided to use WinGet PS module vs. parsing string output from CLI tool
$WinGetPsModule = Get-Module -Name Microsoft.WinGet.Client -ListAvailable
if($null -eq $WinGetPsModule){
Write-Error "Failed to check for PowerShell update: WinGet PS module not installed."
return
}
# Disables pwsh update check
if($env:POWERSHELL_UPDATECHECK -ne "OFF"){
[System.Environment]::SetEnvironmentVariable("POWERSHELL_UPDATECHECK", "OFF")
}
# Storing last update check time in env variable
if($null -eq $env:PSLastUpdateCheck){
[System.Environment]::SetEnvironmentVariable("PSLastUpdateCheck", $CurrentDateTime.ToString())
$LastUpdateCheck = $CurrentDateTime
}
else{
$LastUpdateCheck = [datetime]::Parse($env:PSLastUpdateCheck)
}
$TimeSinceLastCheck = New-TimeSpan -Start $LastUpdateCheck -End $CurrentDateTime
if($TimeSinceLastCheck -gt $CheckInterval){
$ReleaseTagStr = Invoke-RestMethod -Uri $StableBuildUri -Method Get | Select-Object -ExpandProperty ReleaseTag
$LatestReleaseVersion = [System.Management.Automation.SemanticVersion]::Parse($ReleaseTagStr.Substring(1))
if($LatestReleaseVersion -gt $CurrentVersion){ # New release is available
$WinGetVersion = [version](Find-WinGetPackage -Id Microsoft.PowerShell -MatchOption Equals | Select-Object -ExpandProperty Version)
if($LatestReleaseVersion -eq $WinGetVersion){ # WinGet manifest has been updated for new release
$Yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Yes"
$No = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "No"
$Choices = [System.Management.Automation.Host.ChoiceDescription[]]($Yes, $No)
$NotificationLineOne = " A new PowerShell stable release is available: $ReleaseTagStr `n"
$NotificationLineTwo = " Would you like to upgrade now? "
$Prompt = "`e[7m" + $NotificationLineOne + $NotificationLineTwo + "`e[0m"
$ShouldUpgrade = $Host.UI.PromptForChoice($Prompt, " ", $Choices, 0)
if($ShouldUpgrade -eq 0){
Update-WinGetPackage -Id Microsoft.PowerShell
}
}
else{ # WinGet manifest has not been updated yet
return
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment