PowerShell: Deploy Choco Apps

Deployment Instructions:
  1. Create a batch file with this content to call this PowerShell Script
@echo off
set ScriptPath=%~dp0
set ScriptName=deployChocoApps.ps1
PowerShell -ExecutionPolicy Bypass -Command "&'%ScriptPath%%ScriptName%' -Verbose"

Explanation: Powershell will not execute at startup if the computer cannot contact a DC.

2. Ensure that the VPN client perform ‘gpupdate’ upon connection to the domain. Here’s an example for Forticlient:


Explanation: Fortinet Forticlient recommended xml config addition to enable VPN users to map drives and pull GPOs upon successful VPN connections

3. Create a GPO and apply it at a test OU Container
Create GPO > edit new GPO > User configuration > Preferences > Control Panel Settings > Scheduled Tasks > right-click on scheduled tasks > New > Scheduled Task (At Least Windows 7) > Input these properties:
– Name = Deploy Choco Apps
– Action = replace
– When running the task, use the following user account = NT Authority\System
– Run whether user is logged on or not = True
– Run with highest privileges = Checked
– Hidden = Checked
– Triggers = At Startup, repeat the task every 1 hour indefinitely, enabled
– Actions = Start a program
– Program Script = \\%userdnsdomain%\sysvol\%userdnsdomain%\scripts\deployChocoApps\deployChocoApps.ps1
– start in = \\%userdnsdomain%\sysvol\%userdnsdomain%\scripts\deployChocoApps
– arguments = leave blank or -NonInteractive -WindowStyle Hidden -executionpolicy bypass -ErrorAction SilentlyContinue
– Settings = Allow task to run on demand
– Common = Remove this item when it is no longer applied
– Click OK to apply

# deployChocoApps.ps1
# Purpose: to check whether a computer is domain connected and use choco to maintain certain mandatory applications

# User entered variables
$clientApps=@( # keyword-search, version, installation-appName

# Stagger execution timing of script execution
$randomInterval=get-random -Minimum 0 -Maximum 50.00
#start-sleep $randomInterval # Uncomment this line to stagger check-ins

# Autogen variables
$privateRepo="'$privateRepoName' -s '$privateRepoUrl' --priority=$priority"
$computerRole=switch ((Get-CimInstance -ClassName Win32_OperatingSystem).ProductType){
                1 {'client'} # ClientOs
                2 {'domaincontroller'} #ServerOs with DC role
                3 {'memberserver'} #ServerOs machines
$installedApps=Get-CimInstance -ClassName win32_InstalledWin32Program -ErrorAction Stop|select Name,Version
            try {
                return $true
                return $false

function higherVersion ($a,$b){
    # This assumes the query as version $a is greater than $b by reconstructing PowerShell version object
    [void]($a -match $regexVersion)
1..4|%{new-variable "a$_" -value $matches[$_] -force}   
    [void]($b -match $regexVersion)
1..4|%{new-variable "b$_" -value $matches[$_] -force}
    return [Version]::new($a1,$a2,$a3,$a4) -gt [Version]::new($b1,$b2,$b3,$b4)

function chocoAppsMaintenance{
        # Install Chocolatey from the Intranet private repo
        if (!(Get-Command choco.exe -ErrorAction SilentlyContinue)) {
        Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://choco.kimconnect.com/install.ps1'))}
        # Set private repo source if it doesn't exist. Courtesy of Tyler Kocheff
        $sources=choco source list
        $privateRepoExists=$sources -match $privateRepoName        
        if (!$privateRepoExists){
            invoke-expression "choco source add -n=$privateRepo"
        # Install app if it's not already there, or upgrade if its version is outdated        
        $chocoInstalledApps=choco list -l

        foreach ($app in $apps){
            $chocoAppExists=$chocoInstalledApps|?{$_ -like "*$appName*"|select -First 1}
            $chocoVersion=.{[void]($chocoAppExists -match ' ([\d+\.]+)');if($matches){return $matches[1]}else{0}}
            $isChocoLowerVersion=higherVersion $appVersion $chocoVersion            
            $appwizAppExists=.{$matchApp=$installedApps|?{$_.Name -like "*$appName*"|select -First 1 }
                $isAppwizLowerVersion=higherVersion $appVersion $appwizVersion

            write-host "Checking $appName $appVersion`r`nChoco: $chocoVersion`r`nAppwiz: $appwizVersion"
            if (!$chocoAppExists -and !$appwizAppExists){choco install $appInstall -y}
            elseif ($isChocoLowerVersion -and $isAppwizLowerVersion){choco upgrade $appInstall -y}       
        # Upgrade all choco installed apps
        # choco upgrade all -y            

    if($computerRole -eq 'client'){
        chocoAppsMaintenance $clientApps $installedApps $privateRepo
    }elseif($computerRole -eq 'memberserver'){
        chocoAppsMaintenance $serverApps $installedApps $privateRepo
    write-warning "$env:computername is not connected to the domain"

Leave a Reply

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