Worklet: Install Powershell 5.1 on Windows 7 via Chocolatey

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.

Evaluation

[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
        }

Remediation

# Modified from Chocolatey Offline installation. 
# https://chocolatey.org/docs/how-to-setup-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 = 'https://chocolatey.org/7za.exe'
$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 "chocolatey.zip"
  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
    $process.BeginOutputReadLine()
    $process.WaitForExit()
    $exitCode = $process.ExitCode
    $process.Dispose()

    $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 Like

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.

1 Like