Sorting bits into bytes...

VMware Horizon Client Version in vROps

One of the questions I often get from the Horizon Admins is that they like to know which Horizon Client version the end users are using. I tried to solve this question multiple times in the past, without any success. So I thought why not ask help from my fellow EUC guys. Within a couple of minutes Jesper and Michiel jumped to my help. They provided me with a Powershell script which outputs the client version used by the end users. Now lets combine that with my skills to write a Powershell script that shows the Horizon client version in vROps. And that’s exactly what this script does. It gets the client versions from the Horizon connection server. Next the users are looked up in vROps and a new custom metric is added to them.

 

<#

Author: Kabir Ali - info@kablog.nl
Scriptname: VMware Horizon Client Version (VHCV)
Version: 1.0 (Tested)
Date: Feb 11 2021
Why: Security is important.
Remark: Test setup
        vROps Version: 8.2.0 (16949153)
        VMware Horizon 7.12

Example: .\VHCV.ps1 -ConnectionServer "HorizonConnectionServer.local.domain" -ConnectionUser "VDI-Admin" -ConnectionPass "VMware1!" -vROpsServer "vROps.local.domain" -vROpsUser "vROps-Admin" -vROpsPass "VMware1!"

#>

Param (
    
    [Parameter(Mandatory = $true)][string]$ConnectionServer,
    [Parameter(Mandatory = $true)][string]$ConnectionUser,
    [Parameter(Mandatory = $true)][string]$ConnectionPass,
    [Parameter(Mandatory = $true)][string]$vROpsServer,
    [Parameter(Mandatory = $true)][string]$vROpsUser,
    [Parameter(Mandatory = $true)][string]$vROpsPass
)

# Functions are required
function ConvertTo-UnixTimestamp {
    $epoch = Get-Date -Year 1970 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0	
 	$input | % {		
        $milliSeconds = [math]::truncate($_.ToUniversalTime().Subtract($epoch).TotalMilliSeconds)
        Write-Output $milliSeconds
    }	
}
function Get-TimeStamp {
    return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
}

### Define Defaults ###
# See Parameters

### vCenter Connection ###

# Lets connect to the Horizon Connection Server
try {
  Connect-HVServer -Server $ConnectionServer -User $ConnectionUser -Password $ConnectionPass
}
Catch {
  Write-Output "Failed to connect to the Horizon Connection Server: $ConnectionServer ... Exiting..."
  Exit
}


### vROps API Connection ###

#Building vROps API string & invoking REST API
$vROpsURL = "https://" + $vROpsServer + "/suite-api/api/"
$vROpsAuthURL = "https://" + $vROpsServer + "/suite-api/api/auth/token/acquire"
$Type = "application/json"
# Creating JSON for Auth Body
$AuthJSON =
"{
  ""username"": ""$vROpsUser"",
  ""password"": ""$vROpsPass""
}"
# Authenticating with API
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Try {
    $vROpsSessionResponse = Invoke-RestMethod -Method POST -Uri $vROpsAuthURL -Body $AuthJSON -ContentType $Type
}
Catch {
    $_.Exception.ToString()
    $error[0] | Format-List -Force
    Write-Output "Failed connecting to vROps: $vROpsServer ... Exiting..."
    Exit
}
# Extracting the session ID from the response
$vROpsSessionHeader = @{"Authorization"="vRealizeOpsToken "+$vROpsSessionResponse.'auth-token'.token
"Accept"="application/json"}


### Generic Code ###

# Query Horizon to get logged on users with the used client version
$query = New-Object "Vmware.Hv.QueryDefinition"
$query.queryEntityType = 'SessionLocalSummaryView'
$qSrv = New-Object "Vmware.Hv.QueryServiceService"
# Users with client version
$UserClientVersions = $qSRv.QueryService_Query($global:DefaultHVServers[0].ExtensionData,$query) |
Select -ExpandProperty Results |
Select -ExpandProperty NamesData |
Select-Object -Property UserName,ClientVersion

# Generate output
write-host "Found a total of" $UserClientVersions.count "users" -ForegroundColor Green
# For every user found look up the user in vROps
foreach ($UserClientVersion in $UserClientVersions) {
    # vROps cant deal with two dots in the version. So lets break 5.4.4 up into 5. (major release) and 44 (minor release number) while removing the last dot.
    $major = $UserClientVersion.ClientVersion.Substring(0,2)
    $minor =  $UserClientVersion.ClientVersion.split('.')[1..2] -join '' 
    $SimpleVersion = "$major$minor" 
    # Do some cleanup to match usernames in vROps
    $JustUserName = $UserClientVersion.UserName
    # Remove domain part
    $CleanUserName = $JustUserName -replace ".local"
    # Generate output
    write-host $UserClientVersion.UserName "is running version:" $UserClientVersion.ClientVersion -ForegroundColor Green
            # Build vROps URL based on username
            $ResourcesURL = $vROpsURL+"resources?resourceKind=User&name=" +$CleanUserName
            # Get data from vROps
            $vROpsUserName = (Invoke-RestMethod -Method GET -Uri $ResourcesURL -Headers $vROpsSessionHeader -ContentType $Type).resourceList
            # Get timestamp to update vROps with
            $EpochTimeNow = (Get-Date | ConvertTo-UnixTimestamp)
            # Create the JSON reply to update vROps
            $JSONData='{
                "stat-content" : [ {
                "statKey" : "Custom Metrics|Horizon Client Version",
                "timestamps" : ['+$EpochTimeNow+'],
                "data" : ['+$SimpleVersion+'],
                "others" : [ ],
                "otherAttributes" : { }
                } ]
            }'
            # Try to add/update the custom metric
            Try {
                $TagJSONResponse = Invoke-RestMethod -Method POST -Body $JSONData -Uri ($vROpsURL+'resources/'+$vROpsUserName.identifier+'/stats') -TimeoutSec 100 -Headers $vROpsSessionHeader -ContentType $Type
                $TagDetailedInfo = $TagJSONResponse.value
                write-host "Update successful on" $UserClientVersion.UserName -ForegroundColor Green
                write-host "--- --- --- ---" -ForegroundColor Yellow
            }
            Catch {
                $_.Exception.ToString()
                $error[0] | Format-List -Force
                write-host "Update unsuccessful on" $UserClientVersion.UserName -ForegroundColor Red
            }
            # Fix timeout issues
            sleep 1
}

# Close session and done
write-host "All done" -ForegroundColor Green
Invoke-RestMethod -Method POST -Uri https://$vROpsServer/suite-api/api/auth/token/release -Headers $vROpsSessionHeader -ContentType $Type
Disconnect-HVServer -Server * -Confirm:$false

 

I’ve also created a cool dashboard with the newly added metrics.

First create a Metric Configurations file under:

Administration – Configuration – Metric Configurations – TxtWidgetContent – Add

Name the file HClient and add this:

<p><img style="display: block; margin-left: auto; margin-right: auto;" src="https://nolabnoparty.com/wp-content/uploads/2020/08/horizon-7-configuration-01.jpg" alt="Horizon Client 8" width="602" height="202" /></p>
<p style="text-align: center;">Download the latest VMware Horizon Client. Open this link in a new tab:</p>
<p style="text-align: center;"><a title="Download Horizon Client" href="https://my.vmware.com/en/web/vmware/downloads/info/slug/desktop_end_user_computing/vmware_horizon_clients/horizon_8">Horizon Client</a></p>

 

Next import this view:

https://www.kablog.nl/wp-content/uploads/2021/02/Horizon-Client-Version-View.zip

 

The final step is to import this dashboard:

https://www.kablog.nl/wp-content/uploads/2021/02/Dashboard-2021-02-12-03-19-08-PM.zip

Edit the “Number of sessions” widget and be sure to select your own connection servers!

 

Now you should end up with a dashboard like this:

6 thoughts on “VMware Horizon Client Version in vROps

  1. I’ve imported the view and the dashboard but client version column isn’t populating.

    1. Hi Psy,
      Can you tell me which version you are using? Also do you get some sort of error?

  2. I am using Horizon 7.11 and vrops 8.3.17501340 . Can you please let me know the order of the steps that I need to follow. I first added Hclient file and then dashboards and views in vrops followed by running the powershell script at the top of this page. Powershell script generated client versions in the output but in vrops “Horizon Client dashboard Horizon client column is still empty.

    1. I got this working with vROps Version: 8.2.0 (16949153) and Horizon 7.12. But I don’t think that should matter, so your versions should be fine too.

      I would first add the Hclient file, then the View and lastly the dashboard.

      If you see the version in the Powershell output it should be added to vROps as well. How is your vROps licenced? And has the vROps user enough permissions to add metrics? I believe the user should have atleast all the API permissions.

      1. Thanks for a quick reply. User is a admin user so it should have all permissions. I only see 3 lines in Hclient file none of which looks like metrics. Do we need to run powershell file to add those metrics to vROPS ?

        1. The Hclient file is the top right widget shown in the screenshot. It’s just a link to download the latest Horizon Client.
          Yes you should run the Powershell script. It will grab the versions of each client from the Horizon connection server. Then it’ll push that data into vROps.

          If you look up a Horizon user in vROps do you see any custom properties for that user in the metrics/properties tab?

Leave a Reply