Troubleshooting CITRIX Virtual Apps & Desktops Using PowerShell

Table of Contents

Post Featured Image

When I am health-checking or otherwise working in customerCitrix Virtual Apps and Desktops (CVAD) environments, I often use a PowerShell prompt and scripts to get the information I need and to perform tasks as I find it easier and quicker than using the various Citrix, or Microsoft, consoles for many operations.

In this post I will show you some of the commands, with parameters, that I use. The beauty of being proficient in PowerShell is that once you know how to filter, sort, display, etc with one type of object, returned by a PowerShell function or cmdlet, you can use the exact same knowledge to work with practically every other cmdlet from every other provider – well worth the sometimes steep learning curve!



In a CVAD environment we need the CVAD PowerShell cmdlets which are installed when Citrix Studio is installed although the msi installer files for them exist separately on the CVAD installation ISO so can be installed without Studio if desired.

I typically will have these installed on a “jump box” rather than using a delivery controller directly as that risks resource and stability issues (“oops, I rebooted the wrong machine” said no admin ever).

The easiest way to get the cmdlets you need is to just load everything although in a script I would recommend just adding the specific modules that you need (Get-Command will tell you what module a specified cmdlet resides in). In 1912 LTSR and above we run:


Import-Module -Name Citrix*
(or ipmo Citrix* for short where “ipmo” is the alias for “Import-Module”)

For earlier releases, where modules weren’t available, we run:


Add-PSSnapin -Name Citrix*
(or asnp Citrix* for short where “asnp” is the alias for “Add-PSSnapin”)

Note that if you are using Citrix Cloud, you need to use the Remote PowerShell SDK rather than Studio or the MSIs from the CVAD ISO.

One other thing to bear in mind if you’re not running this on a delivery controller, which I don’t recommend, is that you will need to pass -AdminAddress to the CVAD cmdlets together with the name/address of a delivery controller.

If using Citrix Cloud, the argument to -AdminAddress needs to be an on-premises cloud connector. I’m sure I’ve read somewhere in Citrix documentation that you only need to specify it once, but I’ve had problems with that so specify it for every CVAD cmdlet called, albeit usually via a hash table using PowerShell’s “splatting” feature so if I need to change it, or add an extra common parameter, I can do it in one place.

Another potential “gotcha” is that by default the Citrix cmdlets only return 250 records so if working in a large environment, either in terms of users, VDAs, delivery groups, etc, you may need to use -MaxRecordCount (remember you can tab complete so type -max and hit tab or leave it as “-max” as it is not ambiguous – but not in scripts as it can make them difficult to understand when abbreviations are used) and enter a sufficiently large number, like shown below in figure 1.

Screenshot: Enhancing the scope of the command with -MaxRecordCount

Fig. 1: Using -MaxRecordCount you can return more than the default 250 records

In some of the examples I use a variable of type string called ‘ddc’ which I have set as one of the delivery controllers so that I don’t reveal its name in the screenshots.

Getting Information

Here are some useful queries, noting that most begin with Get-Broker. To see what cmdlets are available, you can run this
Get-Command Get-Broker*
Pipe the above through Out-GridView (alias ogv) to see in a handy, filterable and sortable, table.

Alternatively, enter Get-Broker and either hit the tab key to cycle through the list of commands or hit ctrl+space to bring a cursor selectable list up on screen as seen in Figure 2.

Screenshot: List of available cmdlets in the Citrix Module

Fig. 2: Get-Broker brings up a cursor selectable list of all available cmdlets

You can also use the Get-Help cmdlet on them, with optional -ShowWindow or -OnLine parameters, to get more detail and to see examples of their usage.


Q1. How many sessions are there in total, including connected and disconnected?

Get-BrokerSession -AdminAddress $ddc -MaxRecordCount 10000 | measure | select count


Q2. What is the breakdown of active versus disconnected sessions?

Get-BrokerSession @commonCVADparameters | Group-Object -Property SessionState

Screenshot of the command used to display a breakdown of active versus disconnected sessions

Fig. 3: Output of the Command described above

The “Connected” state is where there is a logon in progress.


Q3. What connected sessions have been idle for more than 30 minutes?

$activeSessions = Get-BrokerSession @commonCVADparameters -SessionState Active
$activeSessions|where IdleDuration -gt "00:30:00"|select machinename,username,client*,starttime,idle* | Out-GridView
Note that here we get all active sessions, as in not disconnected, and store them in a variable. This way, we can perform analysis of this data without having to fetch it repeatedly, although the downside is that the data does not auto refresh.

Also note, that we filter in the cmdlet itself (-SessionState), where possible, rather than piping through Where-Object (alias where or ?) as that is faster because using Where-Object retrieves the entire result set and then filters it (figure 4).

Screenshot: A list of all active sessions

Fig. 4: With the command described above, you receive a list of all active sessions


Q4. When and where did user billybob logon?

Get-BrokerSession -UserName guyrleechbillybob @commonCVADparameters | select machinename,client*,DesktopGroupName,CatalogName,starttime

Screenshot: Login information of a certain user

Fig. 5: With the command described above you can retrieve information about the last login of a certain user


Q5. How many machines are registered and not in maintenance mode per delivery group?

Get-BrokerMachine -InMaintenanceMode $false -RegistrationState Registered @commonCVADparameters | group DesktopGroupName|select count,name|sort count

Screenshot: List of all CVAD Machines that are registered and not in maintenance mode, sorted by delivery group

Fig. 6: List of all CVAD machines that are registered and not in maintenance mode, sorted by delivery group


Q6. Which machines have the most user sessions, e.g., do we have an overloaded machine or is load balancing work ok?

Get-BrokerMachine @commonCVADparameters | Sort SessionCount -Descending|select -first 10 machinename, sessioncount, DesktopGroupName, last*|Out-GridView

Screenshot of Citrix Studio, displaying a list of the maxhines with the most user sessions

Fig. 7: A list of the machines that have the most user sessions, displayed in Citrix Studio


Q7. Show Delivery Group Statistics

Get-BrokerDesktopGroup | select Name,Desktop*,Enabled,InMaintenanceMode,Total*|ogv -PassThru

Screenshot of Delivery group statistics in Citrix Studio

Fig. 8: Delivery group statistics in Citrix Studio

Note the use of -PassThru to Out-GridView so the selected items in the grid view – when “OK” is pressed – will be made available where the cmdlet was called from.

Alternatively, they can be piped through Set-ClipBoard (alias scb) so that the data can be pasted into Notepad, an email, OneNote, change control notes, etc.

Screenshot: Delivery Group Statistics pasted into Notepad

Fig. 9: You can paste the data into notepad via Set-ClipBoard

Performing Actions

In most cases, we can pipe the results from the previous queries into cmdlets to take action. But please ensure that you know the implications/impact of the action you are performing and that you are only operating on selected sessions/users, machines, etc rather than say logging off all 5000+ current sessions rather than the one user having an issue!

Enable Maintenance Mode

Set-BrokerMachine -MachineName GUYRLEECH\GLXA19PVS41 -InMaintenanceMode $true
One can also pipe the results of Get-BrokerMachine into Set-BrokerMachine.


Message Users

You can even create custom Notification via Send-BrokerSessionMessage, as can be seen in figure 10.

Get-BrokerSession -MachineName GUYRLEECH\GLXA19PVS41 @commonCVADparameters | Send-BrokerSessionMessage -Title "Message from Guy Leech" -MessageStyle Critical -Text "Please logoff & back on as an urgent reboot is required"
Screenshot: A custom popup notifiction created in PowerShell

Fig. 10: A custom popup notification created in PowerShell

Note that this will not prompt the users nor give them a grace period so ensure they are expecting their session to be logged off!


Logoff All Sessions for a Specific User

Get-BrokerSession -UserName guyrleech\billybob @commonCVADparameters | Stop-BrokerSession
As above, this will not prompt the user nor give them a grace period.

About the author: