Install Apps on Remote Computers via WinRM & Chocolatey

Version A:

[string[]]$computers=@(
	'SERVER01',
	'SERVER02',
	'SERVER03'
)
[string]$chocoAppName='pgadmin4'
[version]$minVersion='6.0'

$results=[hashtable]@{}
foreach ($computer in $computers){
    $session=new-pssession $computer
    if($session.State -eq 'Opened'){
        $result=invoke-command -computer $computer -scriptblock{
            param($appName,$minVersion)
            # Install Chocolatey
            if (!(Get-Command choco.exe -ErrorAction SilentlyContinue)) {
                [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
                Set-ExecutionPolicy Bypass -Scope Process -Force;
                iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))}
            $chocoList=choco list -l
            $installedApps=$chocoList|%{
                $appLine=([regex]'^([\w-_]+)\s([\d\.]+)$').matches($_).Value;
                if($appLine){$appLine}
            }
            $appsList=.{
                $apps=[hashtable]@{}    
                foreach($x in $installedApps){                        
                    if($null -ne $x){
                        $y=$x.Split(' ')
                        $apps+=@{$y[0]=$y[1]}
                    }
                    }
                return $apps
                }
            [bool]$alreadyInstalled=$appName -in $appsList.GetEnumerator().Name
            [version]$installedVersion=if($alreadyInstalled){$appsList.$appName}else{$null}
            if($alreadyInstalled -and $installedVersion -ge $minVersion){
                write-host "$appName $installedVersion has already been installed on $env:computername" -ForegroundColor Green
                return $true		
            }else{
                write-host "Installing $appName on $env:computername..."
                $null=choco install notepad2 -y;
                $chocoList=choco list -l
                $installedApps=$chocoList|%{
                    $appLine=([regex]'^([\w-_]+)\s([\d\.]+)$').matches($_).Value;
                    if($appLine){$appLine}
                }
                $appsList=.{
                    $apps=[hashtable]@{}    
                    foreach($x in $installedApps){                        
                        if($null -ne $x){
                            $y=$x.Split(' ')
                            $apps+=@{$y[0]=$y[1]}
                        }
                        }
                    return $apps
                    }
                [bool]$installedSuccess=$appName -in $appsList.GetEnumerator().Name
                if($installedSuccess){
                    write-host "$appName has been installed on $env:computername successfully" -ForegroundColor Green
                    return $true
                }else{
                    write-host "$appName has NOT been installed on $env:computername successfully" -ForegroundColor Yellow
                    return $false
                }
            }
        } -Args $chocoAppName,$minVersion        
        $results+=@{$computer=$result}
        remove-pssession $session
    }else{
        write-warning "unable to connect to $computer"
    }
}
foreach ($item in $results.GetEnumerator()){
	write-output "$($item.Name): $($item.value)"
}

Version B:

$computernames='dev01','dev02'
$appName='prometheus-windows-exporter.install'

function installChocoApps{
  param(
    $appName='googlechrome',
    $computernames=$env:computername
  )
  $results=[hashtable]@{}
  $command="choco install $appName -y"
  $scriptBlock={
    param($command)
    $ErrorActionPreference='stop'
    try{
      write-host "$env:computername`: executing '$command' ..."
      if (!(Get-Command choco.exe -ErrorAction SilentlyContinue)) {
        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
        Set-ExecutionPolicy Bypass -Scope Process -Force;
        iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))}
      invoke-expression $command
      return $true
    }catch{
      write-warning $_
      return $false
    }
  }
  $sessionIncludePort=New-PSSessionOption -IncludePortInSPN
  foreach ($computerName in $computernames){
      $session=try{
                    New-PSSession -ComputerName $computername -ea Stop
                  }catch{
                    New-PSSession -ComputerName $computername -SessionOption $sessionIncludePort
                  }
      if($session.state -eq 'Opened'){
        [bool]$result=invoke-command -session $session -scriptblock $scriptBlock -Args $command
        remove-pssession $session
        $results+=@{$computerName=$result}
      }else{
        write-warning "unable to connect to $computerName"
        $results+=@{$computerName='Unable to connect'}
      }
  }
  return $results
}

installChocoApps $appName $computerNames

Leave a Reply

Your email address will not be published. Required fields are marked *