11name : Install PowerShell
22description : |
3- Install a specific version — or the latest stable version— of PowerShell Core
3+ Install a specific version, or the latest stable version, of PowerShell Core
44 on any GitHub runner (Linux, macOS, Windows).
55 Skips the install if the requested version is already present.
66author : PSModule
2929 run : |
3030 # Install-PowerShell
3131 set -e
32-
3332 echo "Requested version: [$REQUESTED_VERSION]"
3433
3534 # Only resolve to latest version if explicitly set to 'latest' (case-insensitive)
@@ -73,30 +72,26 @@ runs:
7372 URL="https://github.com/PowerShell/PowerShell/releases/download/v${REQUESTED_VERSION}/${DEB_NAME}"
7473 echo "Downloading from: $URL"
7574 wget -q "$URL" -O "$DEB_NAME"
76- echo "Starting installation of PowerShell [$REQUESTED_VERSION) ]..."
75+ echo "Starting installation of PowerShell [$REQUESTED_VERSION]..."
7776 sudo dpkg -i "$DEB_NAME" || sudo apt-get -f install -y
78- echo "Installation complete. PowerShell [$REQUESTED_VERSION] is now available."
7977 elif command -v rpm >/dev/null; then
8078 # RHEL/Fedora/CentOS based
8179 echo "Detected RHEL/Fedora/CentOS based system..."
82-
8380 if [[ "$ARCH" == "aarch64" ]]; then
8481 RPM_NAME="powershell-${REQUESTED_VERSION}-1.rh.${ARCH}.rpm"
8582 else
8683 RPM_NAME="powershell-${REQUESTED_VERSION}-1.rh.x86_64.rpm"
8784 fi
88-
8985 URL="https://github.com/PowerShell/PowerShell/releases/download/v${REQUESTED_VERSION}/${RPM_NAME}"
9086 echo "Downloading from: $URL"
9187 wget -q "$URL" -O "$RPM_NAME"
92- echo "Starting installation of PowerShell [$REQUESTED_VERSION) ]..."
88+ echo "Starting installation of PowerShell [$REQUESTED_VERSION]..."
9389 sudo rpm -i "$RPM_NAME" || sudo yum install -y "$RPM_NAME"
94- echo "Installation complete. PowerShell [$REQUESTED_VERSION] is now available."
9590 else
9691 echo "Unsupported Linux distribution. Cannot determine package format."
9792 exit 1
9893 fi
99- echo "PowerShell [$REQUESTED_VERSION] installed successfully ."
94+ echo "Installation complete. PowerShell [$REQUESTED_VERSION] is now available ."
10095
10196 - name : Install PowerShell (macOS)
10297 if : runner.os == 'macOS'
@@ -108,7 +103,6 @@ runs:
108103 run : |
109104 # Install-PowerShell
110105 set -e
111-
112106 echo "Requested version: [$REQUESTED_VERSION]"
113107
114108 # Only resolve to latest version if explicitly set to 'latest' (case-insensitive)
@@ -151,15 +145,13 @@ runs:
151145
152146 URL="https://github.com/PowerShell/PowerShell/releases/download/v${REQUESTED_VERSION}/${PKG_NAME}"
153147 echo "Downloading from: $URL"
154-
155148 echo "Starting installation of PowerShell [$REQUESTED_VERSION]..."
156149
157150 if ! curl -sSL "$URL" -o "$PKG_NAME"; then
158151 echo "Error: Failed to download PowerShell package"
159152 exit 1
160153 fi
161154 sudo installer -pkg "$PKG_NAME" -target /
162-
163155 echo "Installation complete. PowerShell [$REQUESTED_VERSION] is now available."
164156
165157 - name : Install PowerShell (Windows)
@@ -173,7 +165,7 @@ runs:
173165 # Install-PowerShell
174166 Write-Host "Requested version: [$env:REQUESTED_VERSION]"
175167
176- # Only resolve to latest version if explicitly set to 'latest' (case-insensitive)
168+ # Resolve 'latest' → concrete version
177169 $req = $env:REQUESTED_VERSION
178170 if ($req -and $req.Trim().ToLower() -eq 'latest') {
179171 $latest = (
@@ -191,29 +183,103 @@ runs:
191183 exit 1
192184 }
193185
186+ # Detect currently installed version (if any)
187+ $detected = $null
194188 try {
195189 $detected = (pwsh -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()')
196190 Write-Host "Currently installed PowerShell version: $detected"
197191 } catch {
198192 Write-Host "PowerShell is not currently installed"
199- $detected = $null
200193 }
201194
202195 if ($detected -eq $env:REQUESTED_VERSION) {
203196 Write-Host "PowerShell $detected already installed. Skipping."
204197 exit 0
205198 }
206199
200+ # Downgrade detection
201+ $isDowngrade = $false
202+ if ($detected -and $detected -ne $env:REQUESTED_VERSION) {
203+ try {
204+ $detectedVersion = [version]$detected
205+ $requestedVersion = [version]$env:REQUESTED_VERSION
206+ if ($detectedVersion -gt $requestedVersion) {
207+ Write-Host "Downgrade detected: $detected → $($env:REQUESTED_VERSION)"
208+ $isDowngrade = $true
209+ } else {
210+ Write-Host "Upgrade detected: $detected → $($env:REQUESTED_VERSION)"
211+ }
212+ } catch {
213+ Write-Host "Warning: Could not compare versions, proceeding with regular installation"
214+ }
215+ }
216+
217+ # If downgrade → fully uninstall current PowerShell 7
218+ if ($isDowngrade) {
219+ Write-Host "Uninstalling existing PowerShell version before downgrade..."
220+
221+ # Search both 64-bit and 32-bit uninstall hives
222+ $regPaths = @(
223+ 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
224+ 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
225+ )
226+
227+ $pwshEntries = Get-ItemProperty -Path $regPaths -ErrorAction SilentlyContinue |
228+ Where-Object {
229+ $_.Publisher -eq 'Microsoft Corporation' -and
230+ $_.DisplayName -like 'PowerShell 7*' -and
231+ $_.DisplayName -notlike '*Preview*' -and
232+ $_.DisplayVersion -and
233+ $_.DisplayVersion.StartsWith($detected)
234+ }
235+
236+ $targetEntry = $pwshEntries | Select-Object -First 1
237+ if (-not $targetEntry) {
238+ Write-Host "Warning: Could not find an uninstall entry for PowerShell $detected"
239+ } else {
240+ $uninstallCmd = if ($targetEntry.QuietUninstallString) {
241+ $targetEntry.QuietUninstallString
242+ } else {
243+ $targetEntry.UninstallString
244+ }
245+
246+ # If the uninstall command is MSI-based and lacks /quiet, add it
247+ if ($uninstallCmd -match 'msiexec') {
248+ if ($uninstallCmd -notmatch '/quiet') { $uninstallCmd += ' /quiet' }
249+ if ($uninstallCmd -notmatch '/norestart') { $uninstallCmd += ' /norestart' }
250+ }
251+
252+ Write-Host "Running uninstall command:`n$uninstallCmd"
253+ $proc = Start-Process 'cmd.exe' -ArgumentList '/c', $uninstallCmd -Wait -PassThru
254+ if ($proc.ExitCode -ne 0) {
255+ Write-Host "Error: Uninstall failed (exit code $($proc.ExitCode))."
256+ exit 1
257+ }
258+
259+ # Double-check removal
260+ try {
261+ $after = (pwsh -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()')
262+ if ($after) {
263+ Write-Host "Error: PowerShell is still present ($after) after uninstall. Aborting downgrade."
264+ exit 1
265+ }
266+ } catch { }
267+ }
268+ }
269+
270+ # Download requested MSI
207271 $msi = "PowerShell-$($env:REQUESTED_VERSION)-win-x64.msi"
208272 $url = "https://github.com/PowerShell/PowerShell/releases/download/v$($env:REQUESTED_VERSION)/$msi"
209273 Write-Host "Downloading from: $url"
210274
211- Write-Host "Starting installation of PowerShell [$($env:REQUESTED_VERSION)]..."
275+ $null = Invoke-WebRequest -Uri $url -OutFile $msi -UseBasicParsing -ErrorAction Stop
212276
213- if (-not (Invoke-WebRequest -Uri $url -OutFile $msi -UseBasicParsing -PassThru)) {
214- Write-Host "Error: Failed to download PowerShell package"
277+ # Install requested version
278+ Write-Host "Starting installation of PowerShell [$($env:REQUESTED_VERSION)]..."
279+ $msiProcess = Start-Process msiexec.exe -ArgumentList '/i', $msi, '/quiet', '/norestart' -Wait -PassThru
280+ if ($msiProcess.ExitCode -ne 0) {
281+ Write-Host "Error: Installation failed (exit code $($msiProcess.ExitCode))."
215282 exit 1
216283 }
217- Start-Process msiexec.exe -ArgumentList '/i', $msi, '/quiet', '/norestart' -Wait
218284
219285 Write-Host "Installation complete. PowerShell [$($env:REQUESTED_VERSION)] is now available."
0 commit comments