The installation of hotfixes for your Citrix environment used to be very simple with Citrix XenApp 6.5. It was just that hotfix which applied to all your systems and you even had a nice hotfix node in Citrix AppCenter.
Now with FMA we have separate hotfixes for VDA Server OS, Desktop OS, Director, Studio, GPMC, you name it. Add the Feature Packs on top, missing documentation and no easy way to check which hotfixes are installed where!
I recently came across a tool called NITCtxPatcher which are a patch manager for Citrix XenApp and XenDesktop.
Simply select the products you want and it will download and create unattended batch files for silent installation. Just be aware of a bug that also shows superseded updates, so make sure to visit each CTX article.
Now if you’re managing a 500-1000 user environment you’re probably cool with that, but at 10.000 – 25.000 seats we need something more powerful.
Let’s try to Automate Citrix Hotfix Installation.
First download and organize your Hotfixes and Feature Packs for DDC, VDA for Desktop and Server OS.
The following scripts will automatically install all MSI and MSP hotfixes in the current folder specified. I would love to get MSI and MSP logging, but the script don´t seem to understand $_ as a log file. If you have any hints, please share in the comments below. In my tests the sleep command was needed as well to successfully install all of them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
Write-Verbose "Setting Arguments" -Verbose $startDTM = (Get-Date) $Vendor = "Citrix" $Product = "XenDesktop" $PackageName = "DDC Hotfixes" $InstallerType = "msi" $Version = "7.6" $FP = "FP2" $LogPS = "${env:SystemRoot}" + "\Temp\$Vendor $Product $PackageName $Version $FP PS Wrapper.log" $LogApp = "${env:SystemRoot}" + "\Temp\$PackageName.log" $Destination = "$Version\Hotfixes\" Start-Transcript $LogPS CD $Destination\$FP\DDC Write-Verbose "$Vendor $Product $PackageName $Version $FP MSI" -Verbose $files = Get-ChildItem -path . -Recurse -Include *.msi $files | ForEach-Object{ Write-Verbose "$_" -Verbose (Start-Process -FilePath msiexec -ArgumentList /i, $_, /qn, /norestart -Wait -Passthru).ExitCode Start-Sleep -m 10000 } Write-Verbose "$Vendor $Product $PackageName $Version $FP MSP" -Verbose $files = Get-ChildItem -path . -Recurse -Include *.msp $files | ForEach-Object{ Write-Verbose "$_" -Verbose (Start-Process -FilePath msiexec -ArgumentList /p, $_, /qn, /norestart -Wait -Passthru).ExitCode Start-Sleep -m 10000 } Write-Verbose "Customization" -Verbose Write-Verbose "Stop logging" -Verbose $EndDTM = (Get-Date) Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalSeconds) Seconds" -Verbose Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalMinutes) Minutes" -Verbose Stop-Transcript |
The Features Pack for VDA is delivered as MSP files, while the Hotfix Update Pack is delivered as MSI.
In the following example I’m installing the FrameHawk components (MSP).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
Write-Verbose "Setting Arguments" -Verbose $startDTM = (Get-Date) $Vendor = "Citrix" $Product = "XenDesktop" $PackageName = "VDA Server Hotfixes" $InstallerType = "msi" $Version = "7.6" $FP = "FP2" $LogPS = "${env:SystemRoot}" + "\Temp\$Vendor $Product $PackageName $Version $FP PS Wrapper.log" $LogApp = "${env:SystemRoot}" + "\Temp\$PackageName.log" $Destination = "$Version\Hotfixes\" Start-Transcript $LogPS CD $Destination\$FP\VDA\Server Write-Verbose "$Vendor $Product $PackageName $Version $FP MSI" -Verbose $files = Get-ChildItem -path . -Recurse -Include *.msi $files | ForEach-Object{ Write-Verbose "$_" -Verbose (Start-Process -FilePath msiexec -ArgumentList /i, $_, /qn, /norestart -Wait -Passthru).ExitCode Start-Sleep -m 10000 } Write-Verbose "$Vendor $Product $PackageName $Version $FP MSP" -Verbose $files = Get-ChildItem -path . -Recurse -Include *.msp $files | ForEach-Object{ Write-Verbose "$_" -Verbose (Start-Process -FilePath msiexec -ArgumentList /p, $_, /qn, /norestart -Wait -Passthru).ExitCode Start-Sleep -m 10000 } Write-Verbose "Customization" -Verbose Write-Verbose "Stop logging" -Verbose $EndDTM = (Get-Date) Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalSeconds) Seconds" -Verbose Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalMinutes) Minutes" -Verbose Stop-Transcript |
Please note that Desktop VDA doesn’t require HDXWMIPROV220WX64001.msi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
Write-Verbose "Setting Arguments" -Verbose $startDTM = (Get-Date) $Vendor = "Citrix" $Product = "XenDesktop" $PackageName = "VDA Desktop Hotfixes" $InstallerType = "msi" $Version = "7.6" $FP = "FP2" $LogPS = "${env:SystemRoot}" + "\Temp\$Vendor $Product $PackageName $Version $FP PS Wrapper.log" $LogApp = "${env:SystemRoot}" + "\Temp\$PackageName.log" $Destination = "$Version\Hotfixes\" Start-Transcript $LogPS CD $Destination\$FP\VDA\Desktop Write-Verbose "$Vendor $Product $PackageName $Version $FP MSI" -Verbose $files = Get-ChildItem -path . -Recurse -Include *.msi $files | ForEach-Object{ Write-Verbose "$_" -Verbose (Start-Process -FilePath msiexec -ArgumentList /i, $_, /qn, /norestart -Wait -Passthru).ExitCode Start-Sleep -m 10000 } Write-Verbose "$Vendor $Product $PackageName $Version $FP MSP" -Verbose $files = Get-ChildItem -path . -Recurse -Include *.msp $files | ForEach-Object{ Write-Verbose "$_" -Verbose (Start-Process -FilePath msiexec -ArgumentList /p, $_, /qn, /norestart -Wait -Passthru).ExitCode Start-Sleep -m 10000 } Write-Verbose "Customization" -Verbose Write-Verbose "Stop logging" -Verbose $EndDTM = (Get-Date) Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalSeconds) Seconds" -Verbose Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalMinutes) Minutes" -Verbose Stop-Transcript |
When you check the installation log you’ll normally see MSI exit code 0 or 3010. There’s nothing wrong with 3010, it just states that a restart is required,
Note: If you upgrade you need to run the following command for Citrix Director.
1 |
C:\inetpub\wwwroot\Director\tools\DirectorConfig.exe /upgrade |
With the release of Citrix Director 7.6 we can now check the updates installed per VM, but there’s no way to get an overview of the complete site like we could in Citrix AppCenter. I would really love a summary overview in Citrix Studio.
After enabling the FrameHawk policy you’ll get the details inside Citrix Director.
To get all details and recommendations you need to run Citrix Scout and upload to Citrix Insight Services (new name for TaaS).
To make things even more complicated, it’s reporting the missing ICATS760WX64010 as critical, but that hotfix is Superseded. The same applies for Recommended Microsoft 2012 R2 Hotfixes. What a complete mess!
So the current situation for Citrix Hotfix and Feature Pack download, installation, management and documentation is a piece of shit!
Citrix TaaS, Oops! Insight Services is really awesome and helpful, but Citrix really needs to act an resolve the reports and the complexity of installing Hotfixes and Feature Packs. It can go really bad…
I would really love to see something similar to vSphere Update Manager and getting rid of XenServer Tools (and VMware) by getting those delivered through Windows Updates instead.
Other Feature Pack 2 Components
Citrix Session Recording which is also a part of Feature Pack 2 has already been cover in the post Complete Guide to Citrix Session Recording.
Below is the script to install the HDX Connector (Server or Desktop OS) and HDX Media Engine (Client Side).
HDX RealTime Connector
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Write-Verbose "Setting Arguments" -Verbose $StartDTM = (Get-Date) $Vendor = "Citrix" $Product = "HDX RealTime Connector" $PackageName = "HDX_RealTime_Connector_1.8_for_Lync_2013" $Version = "1.8" $InstallerType = "msi" $LogPS = "${env:SystemRoot}" + "\Temp\$Vendor $Product $Version PS Wrapper.log" $LogApp = "${env:SystemRoot}" + "\Temp\$PackageName.log" $Destination = "${env:ChocoRepository}" + "\$Vendor\$Product\$Version\$packageName.$installerType" $UnattendedArgs = "/i $PackageName.$InstallerType ALLUSERS=1 /qn /liewa $LogApp" Start-Transcript $LogPS CD $Version Write-Verbose "Starting Installation of $Vendor $Product $Version" -Verbose (Start-Process msiexec.exe -ArgumentList $UnattendedArgs -Wait -Passthru).ExitCode Write-Verbose "Customization" -Verbose Write-Verbose "Stop logging" -Verbose $EndDTM = (Get-Date) Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalSeconds) Seconds" -Verbose Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalMinutes) Minutes" -Verbose Stop-Transcript |
HDX RealTime Media Engine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Write-Verbose "Setting Arguments" -Verbose $StartDTM = (Get-Date) $Vendor = "Citrix" $Product = "HDX RealTime Media Engine" $PackageName = "HDX_RealTime_Media_Engine_1.8_for_Windows" $Version = "1.8" $InstallerType = "msi" $LogPS = "${env:SystemRoot}" + "\Temp\$Vendor $Product $Version PS Wrapper.log" $LogApp = "${env:SystemRoot}" + "\Temp\$PackageName.log" $Destination = "${env:ChocoRepository}" + "\$Vendor\$Product\$Version\$packageName.$installerType" $UnattendedArgs = "/i $PackageName.$InstallerType ALLUSERS=1 /qn /liewa $LogApp" Start-Transcript $LogPS CD $Version Write-Verbose "Starting Installation of $Vendor $Product $Version" -Verbose (Start-Process msiexec.exe -ArgumentList $UnattendedArgs -Wait -Passthru).ExitCode Write-Verbose "Customization" -Verbose Write-Verbose "Stop logging" -Verbose $EndDTM = (Get-Date) Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalSeconds) Seconds" -Verbose Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalMinutes) Minutes" -Verbose Stop-Transcript |
That’s How you Automate Citrix Hotfix Installation. Please share in the comment below how you patch your systems, sharing is caring.
Resources
Wouldn’t it be great if the NITCTXPatcher tool would provide a method to automatically download all the hotfixes these folders used by the Automation Framework:
DDC\32
DDC\64
VDA\Desktop\32
VDA\Desktop\64
VDA\Server\32
VDA\Server\64
Great idea, will pass it on to Andreas
Possible already! But I am working on a method to patch all Citrix products with one call(a script). Then no more directories are necessary. Unfortunately, Citrix makes a lot of strange things with the patches. So I can take the configurable output paths in a short-term release.
Eric,
regarding the log file issue: $_ represents the entire IO.FileInfo object meaning that you have to specify properties. Take a look at this (not tested):
$files |
ForEach-Object {
$msiFile = $_.FullName
$msiLog = ‘{0}\Temp\{1}.log’ -f $env:SystemRoot, $_.BaseName
(Start-Process -FilePath msiexec -ArgumentList /i, $msiFile, /qn, /norestart, /log, $msiLog -Wait -Passthru).ExitCode
Start-Sleep -m 10000
}
Hope this helps
Frank Peter Schultze
@fpschultze
Eric,
I built this script for you. Can you send me the missing path informations for your framework? NitCtxPatcher can run a “custom script” after downloading (in the final Version).
Thank you
Andreas Nick
@nickinformation
$Basefolder = “$ENV:TEMP\CtxPatches\XenDesktop_7.6”
#$CopyTo = “\\YOURSERVER\Patches”
$CopyTo = “C:\temp\patches”
function xBlogCopy {
param (
[String] $source,
[String] $destination
)
if (Test-Path “$source”) {
if (Test-Path “$destination”) {
Remove-Item “$destination” -Force
}
New-Item “$destination” -Type directory -Force
copy “$source\*” “$destination\”
}
}
xBlogCopy -source “$Basefolder\VDAWS32Bit” -destination “$CopyTo\VDA\Desktop\32”
xBlogCopy -source “$Basefolder\VDAWS64Bit” -destination “$CopyTo\VDA\Desktop\64”
#…..
xBlogCopy -source “$Basefolder\VDATS64Bit” -destination “$CopyTo\VDA\Server\64”
Is the NitCtxPatcher download still available? I’m unable to get to the site? Can someone make the tool available please? Thanks.
Works fine, probably just a hickup.
Read thru postings and PDF for NITCtxPatcher. Unclear as to where this gets installed — Delivery Controller, App Server w/ VDA, or both?
Thanks
That would be both.