Starting with XenDesktop 7, Citrix stores the data the Desktop Director displays in a SQL database. Citrix opened up this data via a Monitor Service API that uses OData.  I’m not going to go deep into the details of the API as it is fairly well documented at the eDocs site.  The examples in the documentation show you how to access this data via web browser, Microsoft Excel, and LinqPad.  What I want to do in this article is show you how to use PowerShell with this API.

To start out, let’s take a look at the Citrix Monitor Service schema (click to enlarge):

MonitorDataSchema

Suppose we want to get all sessions as well as the all the connection/disconnections to the session.  The following URL will return the data we want in XML format.

http://localhost/Citrix/Monitor/Odata/v1/Data/Sessions

The trick to get this working with PowerShell is to transform all this information into a nice hierarchical structure.  In the example code below, we use the Invoke-ODataTransform function to do this.

function Global:Invoke-ODataTransform ($records) {

    $propertyNames = ($records | Select -First 1).content.properties |
        Get-Member -MemberType Properties |
        Select -ExpandProperty name

    foreach($record in $records) {

        $h = @{}
        $h.ID = $record.ID
        $properties = $record.content.properties

        foreach($propertyName in $propertyNames) {
            $targetProperty = $properties.$propertyName
            if($targetProperty -is [System.Xml.XmlElement]) {
                $h.$propertyName = $targetProperty.'#text'
            } else {
                $h.$propertyName = $targetProperty
            }
        }

        [PSCustomObject]$h
    }
}

$connections = ""
$uri = "http://localhost/Citrix/Monitor/OData/v1/Data/Sessions?`$expand=Connections"
$connections = Invoke-ODataTransform(Invoke-RestMethod -Uri $uri -UseDefaultCredentials)

foreach($connection in $connections)
{
    $output = $connection | Get-Member -MemberType Properties | ForEach-Object {
        $key = $_.Name
        $value = $connection.$key
        '{0}="{1}"' -f $key,$value
    }

    Write-Host $output
}