Last active
September 3, 2026 12:32
-
-
Save trackd/235bfd8e54e9ec5cee572c028149a89c to your computer and use it in GitHub Desktop.
a way to update powershell without using the msix..
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function Update-PowerShell { | |
| [cmdletbinding()] | |
| <# | |
| .DESCRIPTION | |
| Update PowerShell 7 avoiding the msix mainly... | |
| mostly logic for checking for new versions and setting path + elevating session | |
| .Notes | |
| on first run it downloads https://aka.ms/install-powershell.ps1 and uses that for the actual install logic. | |
| #> | |
| param( | |
| [string]$Path, | |
| [switch]$Preview | |
| ) | |
| $releases = Invoke-RestMethod 'https://api.github.com/repos/PowerShell/PowerShell/releases' | |
| $realPath = if (![string]::IsNullOrEmpty($Path)) { $Path } else { $env:ProgramFiles } | |
| if ($PSBoundParameters['Preview']) { | |
| $InstallPath = Join-Path $realPath 'PowerShell' '7-preview' | |
| $candidate = $releases | Where-Object { $_.prerelease } | Select-Object -First 1 | |
| } | |
| else { | |
| $InstallPath = Join-Path $realPath 'PowerShell' '7' | |
| $candidate = $releases | Where-Object { -not $_.prerelease } | Select-Object -First 1 | |
| } | |
| $Current = Get-Command (Join-Path $InstallPath 'pwsh.exe') -ErrorAction 'Ignore' | |
| if ($Current) { | |
| $candidateVersion = [semver]$candidate.tag_name.TrimStart('v') | |
| $currentVersion = [semver]($Current.FileVersionInfo.ProductVersion -split '\s', 2)[0] | |
| if ($currentVersion -ge $candidateVersion) { | |
| return [PSCustomObject]@{ | |
| Updated = $false | |
| Version = $currentVersion | |
| OnlineVersion = $candidateVersion | |
| InstallPath = $InstallPath | |
| } | |
| } | |
| } | |
| Write-Verbose "A new version of PowerShell is available. Current version: $currentVersion, Latest version: $candidateVersion" | |
| if ($PSHOME -eq $InstallPath) { | |
| $PSCmdlet.ThrowTerminatingError( | |
| [Management.Automation.ErrorRecord]::new( | |
| <# Exception #> [Management.Automation.PSNotSupportedException]::new( | |
| 'Updating PowerShell from the running instance is not supported.' | |
| ), | |
| <# errorId #> 'UpdateNotSupported', | |
| <# ErrorCategory #> [Management.Automation.ErrorCategory]::InvalidOperation, | |
| <# targetObject #> $PSHOME | |
| ) | |
| ) | |
| } | |
| $InstallScript = Join-Path (Split-Path $PSCommandPath -Parent) 'Install-Powershell.ps1' | |
| if (-not (Test-Path $InstallScript)) { | |
| Invoke-RestMethod 'https://aka.ms/install-powershell.ps1' -OutFile $InstallScript | |
| } | |
| function QuoteSingleQuotedLiteral { | |
| param([string]$Value) | |
| "'" + ($Value -replace "'", "''") + "'" | |
| } | |
| $IsAdmin = [Security.Principal.WindowsPrincipal]::new( | |
| [Security.Principal.WindowsIdentity]::GetCurrent()). | |
| IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) | |
| $splat = @{ | |
| Destination = $InstallPath | |
| Preview = $Preview | |
| } | |
| Write-Verbose "Installing PowerShell to $InstallPath. This may take a few minutes.." | |
| if ($IsAdmin) { | |
| & $InstallScript @splat | |
| Get-ChildItem -Recurse $InstallPath | Unblock-File | |
| return | |
| } | |
| Write-Warning 'Not running as administrator. Attempting to elevate privileges...' | |
| $sudo = Get-Command sudo.exe -ErrorAction 'Stop' | |
| $command = "& $(QuoteSingleQuotedLiteral $InstallScript) -Destination $(QuoteSingleQuotedLiteral $InstallPath)" | |
| if ($Preview) { | |
| $command += ' -Preview' | |
| } | |
| $command += "; Get-ChildItem -Recurse $(QuoteSingleQuotedLiteral $InstallPath) | Unblock-File" | |
| Write-Verbose "Command: $command" | |
| $encodedCommand = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($command)) | |
| $pwsh = Join-Path $PSHOME 'pwsh.exe' | |
| $switches = @('-NoLogo', '-NonInteractive', '-NoProfile') | |
| & $sudo --preserve-env --inline $pwsh @switches -EncodedCommand $encodedCommand | |
| if ($LASTEXITCODE -ne 0) { | |
| $PSCmdlet.ThrowTerminatingError( | |
| [Management.Automation.ErrorRecord]::new( | |
| <# Exception #> [Management.Automation.PSNotSupportedException]::new( | |
| "PowerShell installation failed with exit code $LASTEXITCODE." | |
| ), | |
| <# errorId #> 'UpdateFailed', | |
| <# ErrorCategory #> [Management.Automation.ErrorCategory]::InvalidOperation, | |
| <# targetObject #> $InstallScript | |
| ) | |
| ) | |
| } | |
| [PSCustomObject]@{ | |
| Updated = $true | |
| Version = $currentVersion | |
| OnlineVersion = $candidateVersion | |
| InstallPath = $InstallPath | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment