Creating a Chocolatey package for the Citrix Virtual Delivery Agent

Apologies for taking so long to get the first blog post of the year out here, but projects are starting left, right and centre, so it’s been a mad start to 2022. Hopefully it will be a better year than the two aberrations we’ve had for 2020 and 2021!

Now, let’s get started – what is Chocolatey?

If you’re not familiar with it, Chocolatey is a package manager for Windows. Those who move in the Linux world will be intimately familiar with package managers – you just issue a command, and every piece of software on your machine updates itself to the latest available version. APT, RPM, Yum, DPKG – there are stacks of package managers for Linux distributions and they all work in a similar fashion.

Windows, typically, is a bit of a queerer beast and traditionally there have not been such concepts as package managers. There are moves afoot to get package managers out there – WinGet is the official Microsoft Windows Package Manager – and hopefully this might become the de facto way that applications are delivered in future. For now, though, WinGet is a little bit immature.

Which brings me to Chocolatey. I’ve used Chocolatey on and off for a few years now, but it’s essentially one of the few established package managers for Windows. It has an online repository full of community packages that you can use, but it also supports running an on-premises or cloud-based enterprise solution so you can control the release management flow more effectively for business users.

Chocolatey checking for updates

Chocolatey can be triggered by the user, by an admin, or in the background such as through a Scheduled Task. If it detects any updates to the installed applications within the repository, then it will apply them. You can also add new applications simply by specifying the name of the package you wish to install.

Using Chocolatey is a no-brainer against monolithic, unwieldy beasts like SCCM. There’s very little supporting infrastructure required, and from a user perspective, it is much smoother and less intrusive. I hate the concept of SCCM “advertising” new software updates and continually bugging you to either install or reboot – it’s much too involved. I use Chocolatey for all of my core applications within my images – a PowerShell script to install all of them at build time, and a regular Scheduled Task to apply updates that the user barely notices. What I love about it is that you can rapidly deploy it and it is vastly scalable.

As I said, Chocolatey does have a community repository that you can use, but personally I prefer within enterprises to use a managed one. A managed repository doesn’t have to mean on-premises – you can host it in an online repository if you wish – but by using a managed repo you maintain control of your release management cycle. There’s nothing to stop you taking the community versions and hosting them in your managed repository – I will cover this and other Chocolatey tricks in a future article – but it does make sense to keep your own repo to protect yourself from anything going wrong. With regards to hosting your repo, you can use solutions like Artifactory, Nexus, MyGet, ProGet, CloudSmith, etc., or you could even use a file share. Personally, I use one of the “simple server” options – I use Chocolatey.Server on a Windows system running IIS. The setup of this is pretty well documented on the Chocolatey site, although I will also cover this in a future article.

What I also do is use the Chocolatey Package Builder to convert my installer packages into Chocolatey packages. It’s fairly simple, but this is a licensed option and requires Chocolatey For Business. You can obtain a trial version of Chocolatey For Business via

Obviously, one of the components I install as one of the “core applications” in my Citrix Virtual Apps and Desktops environments is the Citrix Virtual Delivery Agent. Previously, I would have to write build scripts that contained credentials to access a file share, copy down the required VDA installer, run it with the customized switches, and then clean up after itself. If we could put that into our Chocolatey repo, we’d make the build process much simpler and more secure, simply just needing a “choco install” command rather than multiple lines of code.

A VDA install typically has customized install switches to specify the required options, locations of DDCs, etc. So there is a little bit of work required to get it correctly converted for Chocolatey.

Creating a Chocolatey package for the Citrix VDA

First, you need to obtain the actual VDA source files 🙂 You will need to download the standalone VDA installer for either the Single-User or Multi-User VDA, dependent on what you are creating the package for. This requires a Citrix sign-in to be able to download them directly.

Next, you will need to decide on the install switches you are using. Citrix used to provide a tool called the VDA Command Line Helper which would automatically generate the install switches for you, but for some reason they have pulled this. I’ve been doing some complaining to try and get them to bring it back, but for now you can download the last available version of it from my DropBox folder here.

If you run the VDA Command Line Helper and select the options you require, you can then generate the required set of switches which will appear at the bottom of the interface. Make a note of these as you will need them.

For posterity, the command line switches I ended up with are shown below

/controllers "" /quiet /noreboot /enable_remote_assistance /virtualmachine /enable_real_time_transport /enable_hdx_ports /components vda /includeadditional "Citrix Profile Management WMI Plugin" /exclude "Citrix WEM Agent","User personalization layer","Citrix Files for Outlook","Citrix Files for Windows","Citrix Supportability Tools","Citrix Personalization for App-V - VDA","Machine Identity Service","Citrix Profile Management","Citrix Universal Print Client","Personal vDisk"

Update 21/10/22 – beware Citrix surreptitiously changing the command-line switches/components available! From 2209, the following component names are deprecated for /includeadditional and /exclude

  • Citrix WEM Agent
  • User personalization layer
  • Citrix Files for Outlook
  • Citrix Files for Windows
  • Personal vDisk

Also, one other has been renamed slightly – Citrix Profile Management WMI Plugin is now Citrix Profile Management WMI Plug-in (added a “-“). If you get any of these switches wrong, you will see the Chocolatey install exit with an error code of 6 and an error of “invalid command-line switches” in the CVAD installer log.

Now, the next task is to copy the VDA setup files to the machine with Chocolatey For Business installed. I did this on my IIS server which also hosts the repository.

Get the official version number from your installation file by right-clicking it, choosing Properties, and switching to the Details tab. You need to use the “proper” version number – so for this VDA (which is the 2106 version) the official version number is

Next, right-click on the installation files and you will get an option to “Create Chocolatey Package” as below

Within this interface, you will need to provide the location of the source (which should be automatically populated), an output directory, and the list of arguments that you just gathered in the previous step.

On the “Nuspec Information” tab, fill in the name you will use for the package and the version number that you gathered as well. You can provide other information in this section as required but these two are the bare minimum that you will need.

Click Generate, and it will create the Chocolatey package in your desired output location.

Now, there are a couple of things we need to do at this point that are very important. Firstly, browse to the newly-created package folder and there will be a subfolder called \packagename\Tools which contains a PowerShell script called chocolateyinstall.ps1. You need to edit this file.

Within this file, there are a couple of changes to be made. Search for a string called validExitCodes and change the value of the array from 0 to 0,3010,1641,3 (block shown below with the change made)

  validExitCodes= @(0,3010,1641,3)
  url           = ""
  checksum      = '1C74A4E0EBE0C178CC843A3F43360E687B345704C099712B25F4630B6E5BF16F'
  checksumType  = 'sha256'
  url64bit      = ""
  checksum64    = ''
  checksumType64= 'sha256'
  destination   = $toolsDir

This is done because when the Citrix VDA installer exits it returns an error code of 3 which Chocolatey interprets as a failure, so we are telling it to accept 3 as a success. It also may occasionally return 3010 or 1641 as well (thanks to Sebastian for that information).

Secondly, you will need to check the silentArgs variable. This is the list of switches that we passed across from the VDA Command Line Helper into the Package Builder. There are a couple of issues. Firstly, if your arguments are more than 75 characters long (as mine were), they will be truncated and incomplete. Secondly, the formatting will be incorrect even if they are within the required length.

This is what silentArgs will look like when generated by the Package Builder initially (this is incorrect and will not work)

silentArgs    = "/controllers /quiet /noreboot /enable_remote_assistance /virtualmachine /enable_real_time_transport /enable_hdx_ports /components vda /includeadditional Citrix"

This is what silentArgs should look like to work correctly, so you will need to edit it to match the formatting in the below section

silentArgs    = '/controllers "" /quiet /noreboot /enable_remote_assistance /virtualmachine /enable_real_time_transport /enable_hdx_ports /components vda /includeadditional "Citrix Profile Management WMI Plugin" /exclude "Citrix WEM Agent","User personalization layer","Citrix Files for Outlook","Citrix Files for Windows","Citrix Supportability Tools","Citrix Personalization for App-V - VDA","Machine Identity Service","Citrix Profile Management","Citrix Universal Print Client","Personal vDisk"'

Now, once you have edited and saved the chocolateyinstall.ps1 file you need to repack the package. Browse to the root of the package folder you generated, and delete the .nupkg file (the screenshot below shows two packages, for posterity)

Once you delete the .nupkg file from the root, open an administrative PowerShell window and browse to the folder with the package name (the one with the .nuspec file in it)

What you simply need to do here is run the choco pack command, and it will create a new .nupkg file with the changes in it

Once this is done, I copy the new .nupkg file into the parent folder, and then copy the entire package into the repository folders. On my IIS Chocolatey.Server instance, this means copying all of the generated files into c:\Tools\Chocolatey.Server\App_Data\Packages – change as required for your repository type and/or paths.

So now I have my Citrix VDA rolled up in the Chocolatey repository, installing it is as simple as running the command below

Of course, this isn’t the way you would generally handle this – the core applications install would be invoked via Chocolatey as part of an install script – I use Packer for this and simply add the command to the required section. The installer does need a reboot afterwards to initialize all of the Citrix VDA services properly – this is easy enough to do with tools like Packer.

When a new VDA comes out, you can simply repeat the above process to package up the new VDA and simply upgrade your existing ones by using Chocolatey with the upgrade command, or you could rebuild your target machines completely and pick up the newer VDA as part of the build. Personally I’d choose the latter, but this isn’t suitable for all environments, obviously. Beneath you can see an upgraded VDA package being manually applied by running the choco upgrade all command

I’m totally sold on Chocolatey and the package management approach, although I am aware I am pretty new to getting down and dirty with it and there’s probably stacks of shortcuts I could have taken in this process that I’m currently not aware of. It makes everything so much cleaner and easier to manage, and feels so much more streamlined and, quite frankly, modern, compared to the likes of SCCM. Stay tuned for some more blogs around this as I learn more about it – I’m particularly keen to have a look at the InTune integration.



  1. Hi James, brilliant article, this had me stumped for a while. Out of interest how did you get packer to wait for the vda to initialise after the reboot, before it then continues with other app installations/scripts?

    1. Wasn’t that clever – I just made it wait for five minutes with a PowerShell script 🙂 I think about a minute and a half was sufficient, but I erred on the side of caution

      1. Thanks, I thought along the same lines, but I was doing it inline, rather than a script:
        “type”: “powershell”,
        “inline”: [“Start-Sleep -s 300”]

        So I tried it by calling a script instead. It waits 5 minutes, packer finishes up by installing another application. The machine shuts down and should be ready for use. When I boot the machine up and log in as administrator I can see in the task manager that the Citrix Virtual Apps and Desktop Vda Setup initiates and then goes ahead and finishes off the install.

        So it looks like it only initiates on logon. So I’m assuming packer isn’t logging in to the machine when running the wait script or installing other apps from chocolatey?

        The end of my packer json looks like this:

        “type”: “powershell”,
        “scripts”: [
        “type”: “windows-restart”
        “type”: “powershell”,
        “inline”: [
        “choco feature enable -n allowGlobalConfirmation”,
        “choco install fslogix”,
        “choco install googlechrome”,
        “choco install microsoft-teams.install”,
        “choco install citrixmultiuservda”
        “type”: “windows-restart”
        “type”: “powershell”,
        “scripts”: [
        “type”: “powershell”,
        “inline”: [“choco install adobereader”]

    1. Hi Mathieu

      Hadn’t noticed that. As far as I can see it simply reboots, continues the installation and completes. However I do have a pause of two minutes written into my Packer install script along with an autologon to allow it to complete, so it may be that these parameters are required to achieve success.

Leave a Reply

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