installing-chocolatey-packages-remotely-with-powershell

Installing Chocolatey Packages Remotely with PowerShell

Installing Chocolatey Packages Remotely with PowerShell

One “free” solution for deploying Chocolatey packages remotely is PowerShell. Using PowerShell remoting techniques, software can be deployed in parallel on many different machines at once. In this article, I will demonstrate this.

As I have written previously, Chocolatey is breath of fresh air to Windows sysadmins everywhere, as it allows for a universal way to manage and deploy software in the enterprise. As Chocolatey is best used via its CLI (command line interface) with CMD or PowerShell, there are many different methods one can use to remotely deploy software to client workstations and servers. These solutions could be Puppet, Chef and SCCM among many others.

PowerShell Remoting Example

One command that I find myself using very often is Invoke-Command. This cmdlet allows me run remote commands and scripts on many machines at once, which makes it incredibly powerful. The two main parameters I usually use are ComputerName and ScriptBlock. The ComputerName parameter requires an input of the hostname on which you want to run remote code on. It can be one host or multiple. The ScriptBlock parameter is obviously a block of code you want to run.

In this case, I want to get the status of the User Profile Service on every machine in Active Directory:

$Computers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name

 

Invoke-Command -ComputerName $Computers -ScriptBlock {

    if (Get-Service ProfSvc | Where-Object {$_.Status -eq 'Running'}) {

        Write-Output "$Env:COMPUTERNAME has ProfSvc running"

    }

}

PowerShell checks if the User Profile Service is running, and if it does, it prints the computers name to the output:

WIN-1 has ProfSvc running

WIN-2 has ProfSvc running

WIN-3 has ProfSvc running

WIN-4 has ProfSvc running
 

Chocolatey Install

Whether on a local machine or running on a remote PowerShell session, to install a Chocolatey package is the same command, choco install. To install a package without being prompted add the –y argument. This is something I almost always do.

Here, I want to install Firefox on my local machine:

choco install firefox –y

Just like that, Firefox is installed and ready to be used. What if I want to install multiple packages at once? You can actually do this by just naming more than one package and separate them by a space with choco install.

choco install firefox googlechrome -y

Remotely Install Google Chrome

In this scenario, I need to install Google Chrome on many machines at once. I will first load the computer names into a variable in PowerShell by querying a specific OU in Active Directory (Windows 10). Then, use Invoke-Command with choco install and do some error checking to see if Chocolatey successfully installed Chrome:

$Computers = Get-ADComputer -Filter * -SearchBase "OU=Windows 10,DC=domain,DC=com" | Select-Object -ExpandProperty Name

 

Invoke-Command -ComputerName $Computers -ScriptBlock {

    choco install googlechrome -y | Out-File -FilePath C:\Windows\Temp\choco-googlechrome.txt

    if ($?) {

        Write-Output "$Env:COMPUTERNAME Successful"

    }

    else {

        Write-Output "$Env:COMPUTERNAME Failed"

    }

}

The output would be something like:

WIN10-1 Successful

WIN10-2 Failed

Using the $? variable in PowerShell we can check on each machine to see if the previous command was successful or not. I also redirect output of choco install to a log file under C:\Windows\Temp. The main reason for this is because if we do not redirect output, all of it will come back to our local PowerShell session and it gets VERY difficult to read. In addition, it will make it a bit easier to look deeper into individual logs if needed.

Remotely Upgrade all Chocolatey Software on multiple computers

In this scenario, I have a maintenance window and I want to use it to upgrade all of the Chocolatey packages on multiple machines. Once again, I turn to Invoke-Command in PowerShell to achieve this, but this time I want to upgrade all packages on each machine. For better error checking, I am not going to run the choco upgrade all though. I am going to run each package individually with choco upgrade and place any failed package into a PowerShell hash table.

$Computers = Get-ADComputer -Filter * -SearchBase "OU=Windows 10,DC=domain,DC=com" | Select-Object -ExpandProperty Name

 

 Invoke-Command -ComputerName $Computers -ScriptBlock {

    $Packages = choco list -lo -r  | % {($_.split("|"))[0]}

    foreach ($Package in $Packages) {

        choco upgrade $Package -y | Out-File -FilePath "c:\Windows\Temp\choco-$Package.txt"

        if ($LASTEXITCODE -ne '0') {

           $Results = [PSCustomObject]@{

                ComputerName = $Env:COMPUTERNAME

                Package = $Package

            }

            $Results

        }

    }

}  | Select-Object ComputerName,Package | Sort-Object -Property ComputerName

 

The results would be a sorted list of machines that had any packages fail during an attempt to upgrade:

ComputerName Package

------------ -------

WIN10-1   vagrant

WIN10-1   Gpg4win

WIN10-1   bitvise-ssh-client

WIN10-1   citrix-receiver

WIN10-2    dropbox

Conclusion

While organizations can choose among many tools for software deployment, I have demonstrated that PowerShell remoting is also a viable option. With some intelligent scripting, sysadmins can install or upgrade many machines at once and save a significant amount of time.

Related Posts


Comments
Comments are disabled in preview mode.
Loading animation