Automating VDI golden image patching with PowerShell and Chocolatey

One of my jobs at work is managing and maintaining a VMware Horizon Horizon VDI environment for around 300 users.

We use non-persistent floating desktop pools meaning each virtual desktop is created from a master virtual machine snapshot. This master virtual machine also sometimes referred to as the “Golden Image” contains the base OS and applications.

One of the main benefits of this is that configuration changes only need to be performed on the master virtual machine which is then rolled out to all users who then get an identical image.

Unfortunately the process of booting into the master VM and manually patching Windows, Office and our third-party applications every month was becoming a very time consuming task, so with my limited PowerShell knowledge decided it was time to look at automating this a bit to make things more hands-off.

I know there are others out there who have completely automated the entire patching and deployment of their VDI environments, however for the moment I am only going to focus on patching and updating applications inside of the “Golden Image”

To use both of these scripts you will need to have the Windows Update PowerShell Module installed on your master VM along with the VMware OS Optimization Tool. In my example I am using a VM with Windows 10 Enterprise version 1909 x64 and have the scripts and VMware OS Optimization Tool in a folder “C:\Scripts”

The first script Update-GoldImage.ps1 will update the installed applications and OS then reboot Windows.

# This scrpt will install Chocolatey Package Manager, update installed applications including Windows and Office then restart the computer on completion
# Requires the Windows Update PowerShell Module - https://www.powershellgallery.com/packages/PSWindowsUpdate/2.2.0.2

# Enable and Start Services
Write-Host "Enabling and Starting Services"
Set-Service -Name bits -StartupType Automatic
Set-Service -Name wuauserv -StartupType Automatic
Set-Service -Name ClickToRunSvc -DisplayName "Microsoft Office Click-to-Run Service" -StartupType Automatic
Start-Service -Name bits
Start-Service -Name wuauserv
Start-Service -Name ClickToRunSvc

# Install Chocolatey Package Manager
Write-Host "Installing Chocolatey Package Manager"
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

# Update Adobe Actobat Reader DC
Write-Host "Updating Adobe Acrobat Reader DC"
choco upgrade adobereader -y -yes -confirm

# Update Microsoft Edge
Write-Host "Updating Microsoft Edge"
choco upgrade microsoft-edge -y -yes -confirm

# Update Google Chrome
Write-Host "Updating Google Chrome"
choco upgrade googlechrome -y -yes -confirm

# Update Mozilla Firefox
Write-Host "Updating Mozilla Firefox"
choco upgrade firefoxesr -y -yes -confirm --params "/l:en-GB /NoTaskbarShortcut /NoDesktopShortcut /NoAutoUpdate /RemoveDistributionDir"

# Update VLC Media Player
Write-Host "Updating VLC Media Player"
choco upgrade vlc -y -yes -confirm

# Update GIMP
Write-Host "Updating GIMP"
choco upgrade gimp -y -yes -confirm

# Update Windows
Write-Host "Updating Windows"
Import-Module PSWindowsUpdate
Get-WUInstall -Install -AcceptAll -IgnoreReboot

# Update Microsoft Office
Write-Host "Updating Microsoft Office"
cd "C:\Program Files\Common Files\microsoft shared\ClickToRun"
.\OfficeC2RClient.exe /update user displaylevel=false forceappshutdown=true

# Sleep for 5 minutes before proceeding with the next task
Write-Host "Waiting for operation to complete"
Start-Sleep -s 300

The second script Finalise-GoldImage.ps1 will stop and disable services and scheduled tasks, uninstall Chocolatey then clean up the OS and shut down Windows.

# This script will stop relevant services/tasks, uninstall Chocolatey Package Manager, clean up the OS then shutdown the VM to prepare it for snapshotting
# Requires the VMware OS Optmization Tool for final clean up process - https://flings.vmware.com/vmware-os-optimization-tool

# Stop and Disable Services
Write-Host "Stopping and Disabling Services"
Stop-Service -Name bits
Stop-Service -Name wuauserv
Stop-Service -Name ClickToRunSvc 
Set-Service -Name bits -StartupType Disabled
Set-Service -Name wuauserv -StartupType Disabled
Set-Service -Name ClickToRunSvc -DisplayName "Microsoft Office Click-to-Run Service" -StartupType Disabled
Set-Service -Name gupdate -DisplayName "Google Update Service (gupdate)" -StartupType Disabled
Set-Service -Name gupdatem -DisplayName "Google Update Service (gupdatem)" -StartupType Disabled
Set-Service -Name edgeupdate -DisplayName "Microsoft Edge Update Service (edgeupdate)" -StartupType Disabled
Set-Service -Name edgeupdatem -DisplayName "Microsoft Edge Update Service (edgeupdatem)" -StartupType Disabled

# Disable Scheduled Tasks
Write-Host "Disabling Scheduled Tasks"
Disable-ScheduledTask -TaskName "Adobe Acrobat Update Task"
Disable-ScheduledTask -TaskName "GoogleUpdateTaskMachineCore"
Disable-ScheduledTask -TaskName "GoogleUpdateTaskMachineUA"
Disable-ScheduledTask -TaskName "MicrosoftEdgeUpdateTaskMachineCore"
Disable-ScheduledTask -TaskName "MicrosoftEdgeUpdateTaskMachineUA"

# Uninstall Chocolatey Package Manager
Write-Host "Uninstalling Chocolatey Package Manager"
Remove-Item -Path "C:\ProgramData\chocolatey" -Recurse -Force

# Clean up Image
Write-Host "Cleaning up Image"
Remove-Item -Path "C:\Users\Public\Desktop\*" -Recurse -Force
Remove-Item -Path $Env:TEMP\* -Recurse -Force
Remove-Item -Path "C:\Windows\Temp\*" -Recurse -Force
Remove-Item -Path "C:\Windows\SoftwareDistribution\*" -Recurse -Force
cd "C:\Scripts\OSOT"
.\VMwareOSOptimizationTool.exe -f all

# Set Execution Policy
Write-Host "Setting PowerShell Execution Policy to Restricted"
Set-ExecutionPolicy Restricted -Force

# Shutdown VM
Write-Host "Shutting down Computer"
Stop-Computer -ComputerName localhost

And that’s it! You can add or remove anything when using these scripts in your environment, hopefully as time goes on I will improve these a bit more and look at automating more of my Horizon deployment process.

Happy patching! 🙂

Leave a Reply

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

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.