Skip to content

Instantly share code, notes, and snippets.

@trackd
Last active September 3, 2026 12:32
Show Gist options
  • Select an option

  • Save trackd/235bfd8e54e9ec5cee572c028149a89c to your computer and use it in GitHub Desktop.

Select an option

Save trackd/235bfd8e54e9ec5cee572c028149a89c to your computer and use it in GitHub Desktop.
a way to update powershell without using the msix..
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