1
1
name : Install PowerShell
2
2
description : |
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
4
4
on any GitHub runner (Linux, macOS, Windows).
5
5
Skips the install if the requested version is already present.
6
6
author : PSModule
29
29
run : |
30
30
# Install-PowerShell
31
31
set -e
32
-
33
32
echo "Requested version: [$REQUESTED_VERSION]"
34
33
35
34
# Only resolve to latest version if explicitly set to 'latest' (case-insensitive)
@@ -73,30 +72,26 @@ runs:
73
72
URL="https://github.com/PowerShell/PowerShell/releases/download/v${REQUESTED_VERSION}/${DEB_NAME}"
74
73
echo "Downloading from: $URL"
75
74
wget -q "$URL" -O "$DEB_NAME"
76
- echo "Starting installation of PowerShell [$REQUESTED_VERSION) ]..."
75
+ echo "Starting installation of PowerShell [$REQUESTED_VERSION]..."
77
76
sudo dpkg -i "$DEB_NAME" || sudo apt-get -f install -y
78
- echo "Installation complete. PowerShell [$REQUESTED_VERSION] is now available."
79
77
elif command -v rpm >/dev/null; then
80
78
# RHEL/Fedora/CentOS based
81
79
echo "Detected RHEL/Fedora/CentOS based system..."
82
-
83
80
if [[ "$ARCH" == "aarch64" ]]; then
84
81
RPM_NAME="powershell-${REQUESTED_VERSION}-1.rh.${ARCH}.rpm"
85
82
else
86
83
RPM_NAME="powershell-${REQUESTED_VERSION}-1.rh.x86_64.rpm"
87
84
fi
88
-
89
85
URL="https://github.com/PowerShell/PowerShell/releases/download/v${REQUESTED_VERSION}/${RPM_NAME}"
90
86
echo "Downloading from: $URL"
91
87
wget -q "$URL" -O "$RPM_NAME"
92
- echo "Starting installation of PowerShell [$REQUESTED_VERSION) ]..."
88
+ echo "Starting installation of PowerShell [$REQUESTED_VERSION]..."
93
89
sudo rpm -i "$RPM_NAME" || sudo yum install -y "$RPM_NAME"
94
- echo "Installation complete. PowerShell [$REQUESTED_VERSION] is now available."
95
90
else
96
91
echo "Unsupported Linux distribution. Cannot determine package format."
97
92
exit 1
98
93
fi
99
- echo "PowerShell [$REQUESTED_VERSION] installed successfully ."
94
+ echo "Installation complete. PowerShell [$REQUESTED_VERSION] is now available ."
100
95
101
96
- name : Install PowerShell (macOS)
102
97
if : runner.os == 'macOS'
@@ -108,7 +103,6 @@ runs:
108
103
run : |
109
104
# Install-PowerShell
110
105
set -e
111
-
112
106
echo "Requested version: [$REQUESTED_VERSION]"
113
107
114
108
# Only resolve to latest version if explicitly set to 'latest' (case-insensitive)
@@ -151,15 +145,13 @@ runs:
151
145
152
146
URL="https://github.com/PowerShell/PowerShell/releases/download/v${REQUESTED_VERSION}/${PKG_NAME}"
153
147
echo "Downloading from: $URL"
154
-
155
148
echo "Starting installation of PowerShell [$REQUESTED_VERSION]..."
156
149
157
150
if ! curl -sSL "$URL" -o "$PKG_NAME"; then
158
151
echo "Error: Failed to download PowerShell package"
159
152
exit 1
160
153
fi
161
154
sudo installer -pkg "$PKG_NAME" -target /
162
-
163
155
echo "Installation complete. PowerShell [$REQUESTED_VERSION] is now available."
164
156
165
157
- name : Install PowerShell (Windows)
@@ -173,7 +165,7 @@ runs:
173
165
# Install-PowerShell
174
166
Write-Host "Requested version: [$env:REQUESTED_VERSION]"
175
167
176
- # Only resolve to latest version if explicitly set to 'latest' (case-insensitive)
168
+ # Resolve 'latest' → concrete version
177
169
$req = $env:REQUESTED_VERSION
178
170
if ($req -and $req.Trim().ToLower() -eq 'latest') {
179
171
$latest = (
@@ -191,24 +183,25 @@ runs:
191
183
exit 1
192
184
}
193
185
186
+ # Detect currently installed version (if any)
187
+ $detected = $null
194
188
try {
195
189
$detected = (pwsh -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()')
196
190
Write-Host "Currently installed PowerShell version: $detected"
197
191
} catch {
198
192
Write-Host "PowerShell is not currently installed"
199
- $detected = $null
200
193
}
201
194
202
195
if ($detected -eq $env:REQUESTED_VERSION) {
203
196
Write-Host "PowerShell $detected already installed. Skipping."
204
197
exit 0
205
198
}
206
199
207
- # Check if we need to handle a downgrade scenario
200
+ # Downgrade detection
208
201
$isDowngrade = $false
209
202
if ($detected -and $detected -ne $env:REQUESTED_VERSION) {
210
203
try {
211
- $detectedVersion = [version]$detected
204
+ $detectedVersion = [version]$detected
212
205
$requestedVersion = [version]$env:REQUESTED_VERSION
213
206
if ($detectedVersion -gt $requestedVersion) {
214
207
Write-Host "Downgrade detected: $detected → $($env:REQUESTED_VERSION)"
@@ -221,47 +214,72 @@ runs:
221
214
}
222
215
}
223
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
224
271
$msi = "PowerShell-$($env:REQUESTED_VERSION)-win-x64.msi"
225
272
$url = "https://github.com/PowerShell/PowerShell/releases/download/v$($env:REQUESTED_VERSION)/$msi"
226
273
Write-Host "Downloading from: $url"
227
274
228
- if (-not (Invoke-WebRequest -Uri $url -OutFile $msi -UseBasicParsing -PassThru)) {
229
- Write-Host "Error: Failed to download PowerShell package"
230
- exit 1
231
- }
275
+ $null = Invoke-WebRequest -Uri $url -OutFile $msi -UseBasicParsing -ErrorAction Stop
232
276
277
+ # Install requested version
233
278
Write-Host "Starting installation of PowerShell [$($env:REQUESTED_VERSION)]..."
234
-
235
- if ($isDowngrade) {
236
- # For downgrades, uninstall the existing version first, then install the new one
237
- Write-Host "Downgrade detected - uninstalling existing PowerShell version first..."
238
-
239
- # Find PowerShell installation to uninstall
240
- $uninstallString = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue |
241
- Where-Object { $_.DisplayName -like "*PowerShell*" -and $_.Publisher -eq "Microsoft Corporation" } |
242
- Select-Object -First 1 -ExpandProperty UninstallString
243
-
244
- if ($uninstallString) {
245
- Write-Host "Found existing PowerShell installation, uninstalling..."
246
- # Extract the product code from the uninstall string
247
- if ($uninstallString -match '{[0-9A-F-]+}') {
248
- $productCode = $matches[0]
249
- Write-Host "Uninstalling PowerShell with product code: $productCode"
250
- Start-Process msiexec.exe -ArgumentList '/x', $productCode, '/quiet', '/norestart' -Wait
251
- Write-Host "Uninstall completed"
252
- } else {
253
- Write-Host "Warning: Could not extract product code from uninstall string: $uninstallString"
254
- }
255
- } else {
256
- Write-Host "Warning: Could not find PowerShell installation to uninstall"
257
- }
258
-
259
- # Now install the new version
260
- Write-Host "Installing PowerShell [$($env:REQUESTED_VERSION)]..."
261
- Start-Process msiexec.exe -ArgumentList '/i', $msi, '/quiet', '/norestart' -Wait
262
- } else {
263
- # For upgrades or fresh installs, use regular install
264
- Start-Process msiexec.exe -ArgumentList '/i', $msi, '/quiet', '/norestart' -Wait
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))."
282
+ exit 1
265
283
}
266
284
267
285
Write-Host "Installation complete. PowerShell [$($env:REQUESTED_VERSION)] is now available."
0 commit comments