Overview of Script Samples using PowerCLI for Horizon

February 19, 2022

Automation for VMware Horizon has never been as accessible as it is today. Between your choice of the Horizon REST API and PowerCLI, you can leverage the scripting language or platform of your choice to invoke the underlying APIs. Today I’ll share a few samples of code that I use on a regular basis, along with a couple of tips. The examples below will be provided in PowerShell, but many of them that utilize the REST API are portable to most other languages.

First off, be sure to check up on Automating VMware Horizon 7 with VMware PowerCLI to get a primer on using PowerCLI for Horizon. That will provide you with a baseline to use the following examples, as well as setting you up with the Advanced Functions provided in the VMware.Hv.Helper module.

Connect to the API

Start by connecting to the API, and optionally declare an object to store the session in:

$HVServer = Connect-HVServer -Server connectionserver.domain.tld

Pro Tip: If you’re running PowerCLI from within a Horizon session, and want to connect to the Connection Server, use this code snippet:

$HVServer = Connect-HVServer -Server $env:ViewClient_Broker_DNS_Name

Enumerating The API with ConvertTo-JSON

If you’ve ever wanted to explore the API, then certainly the documentation is a good start. However, there’s another way that involves never having to leave your shell. This is helpful for those times that a certain API call doesn’t return helpful or human-readable information.

$HVServer.ExtensionData.ConnectionServer.ConnectionServer_List() will give you a list of Connection Servers in the connected Horizon Pod, but it’s difficult to do anything with this information, as you can see below:

<p>Description automatically generated

Figure 1: The output of the ConnectionServer_List() method, though not that useful

However, if you pipe that into ConvertTo-JSON, then suddenly you get some more useful information:

$HVServer.ExtensionData.ConnectionServer.ConnectionServer_List() | ConvertTo-JSON

Figure 2: A more useful and informative display, piping ConnectionServer_List() into ConvertTo-JSON

Using Get-HVEvent

I’ll admit that using Get-HVEvent was not that intuitive for me at first. Here’s a primer for how it works.

  1. First, instantiate an object for the Events Database. This will query the pod for the configured Events Database and store it in our new object.

$HVDB = Get-HVEventDatabase

  1. Build an object for the password needed to connect to the Events Database. Note that this will use the password for the SQL Server account that’s already in use for the Events Database.

$HvDbPassword = Read-Host "Please input the password for account $($HVDb.UserName)" -AsSecureString

  1. Third, we’ll use that to make the connection to the Events Database. The naming here doesn't matter, but I try to match parameter names where possible:

$HvDbServer = Connect-HVEvent -DbUserName $HVDb.UserName -DbPassword $HvDbPassword

Now that we’re connected, we can make queries against the database. For example, let’s find all events related to a user connecting to a desktop agent:

Get-HVEvent -HvDbServer $HvDbServer -TimePeriod all -ModuleFilter Agent -MessageFilter "mfrey has logged in to a new session on machine"

We could also list all events with a Severity of Error:

Get-HVEvent -HvDbServer -TimePeriod all -SeverityFilter Error

Perhaps you want to list all events related to administrators:

Get-HVEvent -HvDbServer -TimePeriod all -ModuleFilter Admin

Query Information About Sessions

Session information is another tricky one because there is no single method which will return all sessions for a given Pod. Instead, we must turn to the QueryService. The QueryService can be used for returning information about entities that do not have their own _List() or _Get() methods. Let's walk through that process now.

  1. Create the QueryService object, which may have an odd name, but nonetheless this is no typo:

$QueryService = New-Object VMware.Hv.QueryServiceService

  1. Next up, let's create an object for the QueryDefinition.

$QueryDefinition = New-Object VMware.Hv.QueryDefinition

  1. Now that we have the QueryDefinition object, we need to set the QueryEntityType, which is to say, "what type of object are we querying for?" In this case, we want to query the SessionLocalSummaryView data type.

$QueryDefinition.queryEntityType = 'SessionLocalSummaryView'

  1. Now we're ready to list all of the sessions on the local pod.

$QueryResults = $QueryService.QueryService_Create($HVServer.ExtensionData,$QueryDefinition).Results

If we were to view the results now, you can see that it's not very human-readable:

$QueryResults | Format-Table

<p>Description automatically generated

Figure 3: A table of Horizon Sessions, though not in a readable format

Our previous tip to use ConvertTo-JSON is a bit messy as well, since there's more information than we need. This is where the property NamesData comes in handy. Most query-able entities will return the NamesData property. This property contains mostly human-readable data related to the sessions, so it is good for reporting.

$QueryResults.NamesData | Format-Table -AutoSize

Figure 4: Improve readability of the NamesData property

If you want to filter based on a certain username, you can use a query filter of QueryFilterEquals. We could also use a query filter of QueryFilterContains, though that can be a bit slower in large environments.

$QueryFilterEquals = New-Object VMware.Hv.QueryFilterEquals

$QueryFilterEquals.memberName = 'namesData.userName'

$QueryFilterEquals.value = 'domain\username'

$QueryDefinition.Filter = $QueryFilterEquals

$QueryResults = $QueryService.QueryService_Create($HVServer.ExtensionData,$QueryDefinition).Results


Figure 5: Querying sessions for a specific user

To learn more about the Query Service, visit the ViewAPI Documentation, then look for the Query Service page.


Thanks for reading through my code samples. My hope is that this will help spur ideas for how to improve your scripting of Horizon with PowerCLI.

Be sure to subscribe to the Digital Workspace Tech Zone Blog RSS or check back on this blog post daily to see what we release. We'll add each day's topic to agenda on this page with a link to keep you organized. By the end of this month, we hope that you are comfortable leveraging code samples, VMware Flings, scripting/coding, and leveraging the EUC APIs to automate your workspace!

You can also follow us on Twitter @EUCTechZone to stay updated on the latest EUC content!


Make sure to check out the other blog posts in our 28-day series:


Filter Tags

Workspace ONE Workspace ONE Access Workspace ONE Intelligence Workspace ONE UEM Blog Technical Overview Intermediate Optimize