'Update-to-PS7.ps1'
<#
.SYNOPSIS
Script to download and “install” the portable PowerShell 7 (zip) to C:\powershell without being destructive.
.DESCRIPTION
- Uses GitHub API to get the latest stable PowerShell 7 release
- Installs to $targetRoot
- Unzips the portable archive there
- Adds the install directory to the current user’s PATH
- Leaves pwsh.exe in place so you can launch PowerShell 7 by typing `pwsh`
.NOTES
- Make sure c:\PowerShell exists or alter the path of $targetRoot
- Make sure you close all Powershell.exe, powershell_ise.exe and PWSH.exe windows before running and ONLY open powershell.exe "Run As Administrator"
- This script requires PowerShell 5.1+ for Invoke-RestMethod and Expand-Archive
- Also should be run as a local 'BUILTIN\Administrators' user to enable writing to C:\ or D:\ and modify registry rights for PATH
#>
[CmdletBinding()]
param()
function Test-IsAdmin {
return ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
if (-not (Test-IsAdmin)) {
Throw "This script must be run as Administrator."
}
$targetRoot = 'C:\powershell' #<-- change this for the PowerShell folder path you use
Write-Host "Installing PowerShell 7 to $targetRoot..."
# Check if PowerShell 7 is already installed
if (Test-Path (Join-Path $targetRoot 'pwsh.exe')) {
Write-Host "PowerShell 7 is already installed at $targetRoot. Skipping installation."
return
}
# Prepare target folder
if (-not (Test-Path $targetRoot)) {
New-Item -Path $targetRoot -ItemType Directory | Out-Null
}
Write-Host "Querying GitHub for the latest PowerShell 7 release..."
$release = Invoke-RestMethod `
-Uri 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest' `
-Headers @{ 'User-Agent' = 'PowerShell-Install-Script' }
# Find the portable-win-x64.zip asset (adjust for x86 if you need 32-bit)
$zipAsset = $release.assets `
| Where-Object { $_.name -match 'powershell-.*-win-x64\.zip$' } `
| Select-Object -First 1
if (-not $zipAsset) {
Throw "Could not locate the portable ZIP asset for x64 in release $($release.tag_name)."
}
# Download ZIP to temp
$tempZip = Join-Path $env:TEMP $zipAsset.name
Write-Host "Downloading $($zipAsset.browser_download_url) to $tempZip ..."
Invoke-WebRequest `
-Uri $zipAsset.browser_download_url `
-OutFile $tempZip `
-UseBasicParsing
# Extract
Write-Host "Extracting archive to $targetRoot ..."
Expand-Archive -Path $tempZip -DestinationPath $targetRoot -Force
# Clean up temp ZIP
Remove-Item $tempZip -Force
# Add target to current user’s PATH if not already present
$oldPath = [Environment]::GetEnvironmentVariable('Path','User')
if (-not ($oldPath.Split(';') -contains $targetRoot)) {
Write-Host "Adding $targetRoot to your user PATH..."
$newPath = $oldPath + ';' + $targetRoot
[Environment]::SetEnvironmentVariable('Path',$newPath,'User')
Write-Host "User PATH updated. You will need to open a new shell to see the change."
} else {
Write-Host "$targetRoot is already in your user PATH."
}
Write-Host "`nDone! Open a new terminal window and run 'pwsh' to launch PowerShell 7."

Upgrade to PWSH Without Being Destructive (even for DCs)
by
Tags:
