Worklet: Install Powershell 5.1 on Windows 7 via Chocolatey

  • 4 May 2020
  • 1 reply

Noticed that Windows 7 devices (with the extended support update) weren’t showing software inventory in Automox. After working with Automox support, they discovered that Windows 7 devices need Powershell 5 (supposedly they’ll have a fix for Windows 7 devices soon). I attempted to use the Microsoft provided powershell script to install Windows Management Framework 5.1 (KB3191566) (which installs powershell 5 on Windows 7), but couldn’t get it to run consistently. Tried installing chocolatey and then running ‘choco install powershell’ and it worked consistently.

So that’s what this script does: installs chocolatey offline and then runs ‘choco install powershell’ on Windows 7 machines. It isn’t pretty, but it works. Would appreciate someone with actual Powershell experience/skills to clean up.


[string]$ThisPackagePSHVersion = '5.1.14409.1005'
if ($PSVersionTable -and ($PSVersionTable.PSVersion -ge [Version]$ThisPackagePSHVersion)) {
Write-Warning "PowerShell version, $($PSVersionTable.PSVersion), is already installed."
exit 0
else {
# Powershell 5.1 is not installed, run remediation script
exit 1


# Modified from Chocolatey Offline installation. 
# This script installs Chocolatey and then runs the Windows
# Management Framework 5.1 installation in order to install
# Powershell 5.1 on Windows 7 devices. Could not get the MS provided
# powershell script for KB3191566 to work consistently
# (hangs, high memory usage, etc);but 'choco install powershell'
# seemed to work consistently.

# Tried just using bypass, but unrestricted allowed consistent usage.
# Reset to restricted at the end
Set-ExecutionPolicy Unrestricted;
Set-ExecutionPolicy Bypass -Scope Process -Force;

# Set variables
$localPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('.\')
$package ='chocolatey.0.10.15.nupkg'
$localChocolateyPackageFilePath = Join-Path $localPath $package
$ChocoInstallPath = "$($env:SystemDrive)\ProgramData\Chocolatey\bin"
$unzipMethod = "7zip"
$7zP = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('.\')
$7z = "7za.exe"
$7zipUrl = ''
$7zlocalPath = Join-Path $7zP $7z

# Need to download 7za.exe and the current version of Chocolatey and add as installation files
function Install-ChocolateyFromPackage {
$env:ChocolateyInstall = "$($env:SystemDrive)\ProgramData\Chocolatey"
$env:Path += ";$ChocoInstallPath"
$chocolateyPackageFilePath = Join-Path $localPath $package

if ($chocolateyPackageFilePath -eq $null -or $chocolateyPackageFilePath -eq '') {
throw "You must specify a local package to run the local install."

if (!(Test-Path($chocolateyPackageFilePath))) {
throw "No file exists at $chocolateyPackageFilePath"

$chocTempDir = Join-Path $env:TEMP "chocolatey"
$tempDir = Join-Path $chocTempDir "chocInstall"
if (![System.IO.Directory]::Exists($tempDir)) {[System.IO.Directory]::CreateDirectory($tempDir)}
$file = Join-Path $tempDir ""
Copy-Item $chocolateyPackageFilePath $file -Force

# unzip the package
Write-Output "Extracting $file to $tempDir..."
$7zaExe = Join-Path $tempDir "7za.exe"

$params = "x -o`"$tempDir`" -bd -y `"$file`""
# use more robust Process as compared to Start-Process -Wait (which doesn't
# wait for the process to finish in PowerShell v3)
$process = New-Object System.Diagnostics.Process
$process.StartInfo = New-Object System.Diagnostics.ProcessStartInfo($7zlocalPath, $params)
$process.StartInfo.RedirectStandardOutput = $true
$process.StartInfo.UseShellExecute = $false
$process.StartInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
$process.Start() | Out-Null
$exitCode = $process.ExitCode

$errorMessage = "Unable to unzip package using 7zip. Perhaps try setting `$env:chocolateyUseWindowsCompression = 'true' and call install again. Error:"
switch ($exitCode) {
0 { break }
1 { throw "$errorMessage Some files could not be extracted" }
2 { throw "$errorMessage 7-Zip encountered a fatal error while extracting the files" }
7 { throw "$errorMessage 7-Zip command line error" }
8 { throw "$errorMessage 7-Zip out of memory" }
255 { throw "$errorMessage Extraction cancelled by the user" }
default { throw "$errorMessage 7-Zip signalled an unknown error (code $exitCode)" }

# Call Chocolatey install
Write-Output 'Installing chocolatey on this machine'
$toolsFolder = Join-Path $tempDir "tools"
$chocInstallPS1 = Join-Path $toolsFolder "chocolateyInstall.ps1"

& $chocInstallPS1

Write-Output 'Ensuring chocolatey commands are on the path'
$chocInstallVariableName = 'ChocolateyInstall'
$chocoPath = [Environment]::GetEnvironmentVariable($chocInstallVariableName)
if ($chocoPath -eq $null -or $chocoPath -eq '') {
$chocoPath = 'C:\ProgramData\Chocolatey'

$chocoExePath = Join-Path $chocoPath 'bin'

if ($($env:Path).ToLower().Contains($($chocoExePath).ToLower()) -eq $false) {
$env:Path = [Environment]::GetEnvironmentVariable('Path',[System.EnvironmentVariableTarget]::Machine);

Write-Output 'Ensuring chocolatey.nupkg is in the lib folder'
$chocoPkgDir = Join-Path $chocoPath 'lib\chocolatey'
$nupkg = Join-Path $chocoPkgDir 'chocolatey.nupkg'
if (!(Test-Path $nupkg)) {
Write-Output 'Copying chocolatey.nupkg is in the lib folder'
if (![System.IO.Directory]::Exists($chocoPkgDir)) { [System.IO.Directory]::CreateDirectory($chocoPkgDir); }
Copy-Item "$file" "$nupkg" -Force -ErrorAction SilentlyContinue

# running choco install powershell
Write-Output 'Installing Powershell via Chocolatey'
$env:ChocolateyInstall = "$($env:SystemDrive)\ProgramData\Chocolatey"
$env:Path += ";$ChocoInstallPath"
& C:\ProgramData\chocolatey\bin\choco.exe install powershell -y | out-null

# reset execution policy to restricted
Write-Output 'Resetting execution policy to restricted'
Set-ExecutionPolicy Restricted

# Install Chocolatey
Install-ChocolateyFromPackage $localChocolateyPackageFilePath

1 reply

Follow up - Automox released the update for Windows 7/Powershell 2 software inventory, so this is probably unnecessary unless you want to install chocolatey offline and still install Powershell 5.1.