Gather list of RD sessions from registered servers through the RD Connection Broker

This script was created to output information regarding users that are logged onto the various Remote Desktop farms that are deployed within the organization. This helps with migrations from one environment (2008) to another (2016) due to the information gathered from Active Directory.

The script has been tested on both environments running on Windows Server 2008 and Windows Server 2016. On environments that run Windows Server 2016 I have noticed that session information such as resolutions are not longer registered or gathered and I have not been able to identify why as of yet. If you have an idea why that is or how to gather that information on 2016 or higher environments please leave a comment.

This script includes a function that I shared already named get-ADSIUserInfo and is only included so that the script will function without additional requirements.

Example:
In the below example certain information is removed due to the fact that this is gathered from a live environment.

Invoke-GatherCBUserList Script execution
Invoke-GatherCBUserList after script execution has finished
Invoke-GatherCBUserList after script execution has finished

Code:

<#
  .SYNOPSIS
  Outputs a list of users and information logged onto a RDS environment.
  .DESCRIPTION
  Connects to the specified Connection Broker (environment) and retrieves the list of users and AD information about the user and their RD session.
  .EXAMPLE
	Invoke-GatherCBUserList -CBFQDN myconnbroker.example.com
  .EXAMPLE
  Invoke-GatherCBUserList -CBFQDN myconnbroker.example.com -ClusterName MyCluster
  .PARAMETER CBFQDN
	The FQDN of your connection broker or High Available Connection Broker environment.
  .PARAMETER ClusterName
  The cluster name also known as collection name (within Server Manager) of the environment, this parameter is optional if not specified all clusters/collections are included.
#>
Param(
  [Parameter(Mandatory = $true)]
  [string]$CBFQDN,
  [string]$ClusterName
)

Function get-ADSIUserInfo {
  <#
      .SYNOPSIS
      Gathers user information using ADSI from the current domain on which this is executed unless explicitly specified.
      .DESCRIPTION
      Returns all information which is filled in or default stored on the user object in Active Directory
      .EXAMPLE
      get-ADSIUserInfo -UserAccount marcmuld
      .PARAMETER UserAccount
      The user account name to search for (samaccountname) in Active Directory
   #>
  Param (
    [Parameter(Mandatory = $True)]
    [string]$UserAccount
  )
  $ADSISearcher = New-Object DirectoryServices.DirectorySearcher
  $ADSISearcher.Filter = "(&amp;(objectCategory=person)(objectClass=User)(samaccountname=$($UserAccount)))"
  $ADSIResults = $ADSISearcher.findone()
  return $ADSIResults
}

$ConnectionsTable = New-Object System.Data.DataTable("RDSConnections")
$Cols = @("User Account", "Full Name", "Mail", "Company", "Department", "Division", "Manager", "Manager Mail", "RDS Server", "Used Resolution", "Login DateTime", "Session State", "Cluster Name")
foreach ($col in $cols) {
  $ConnectionsTable.Columns.Add($col) | Out-Null
}

$SessionDirectoryQuery = "Select * from Win32_SessionDirectoryServer"
If ($ClusterName) {
  $SessionDirectoryQuery = "Select * from Win32_SessionDirectoryServer where ClusterName='$($ClusterName)'"
}
$ActiveRegisteredServers = Get-WMIObject -computername "$($CBFQDN)" -Query $SessionDirectoryQuery
$ProgressCountMax = $ActiveRegisteredServers.Count
$ProgressCount = 1
$TotalSessions = 0
ForEach ($RDSServer in $ActiveRegisteredServers) {
  $ProgressMsg = "Processing RD Server with name $($RDSServer.ServerName)"
  Write-Progress -Activity $ProgressMsg -status "$($ProgressCount)/$($ProgressCountMax)" -percentComplete (($ProgressCount / $ProgressCountMax) * 100)
  $SessionsOnServer = Get-WMIObject -computername "$($CBFQDN)" -Query "Select * from Win32_SessionDirectorySession where ServerName ='$($RDSServer.ServerName)'"
  ForEach ($Session in $SessionsOnServer) {
    $row = $ConnectionsTable.NewRow()
    $SessionCreationTime = [System.Management.ManagementDateTimeConverter]::ToDateTime($Session.CreateTime)
    $ADSISearchResults = get-ADSIUserInfo -UserAccount $($Session.UserName)
    $row["User Account"] = $($Session.UserName)
    $row["Full Name"] = $($ADSISearchResults.properties.displayname)
    $row["Mail"] = $($ADSISearchResults.properties.mail)
    $row["Company"] = $($ADSISearchResults.properties.company)
    $row["Department"] = $($ADSISearchResults.properties.department)
    $row["Division"] = $($ADSISearchResults.properties.division)
    $row["Manager"] = "No manager in AD"
    $row["Manager Mail"] = "No manager in AD"
    If ($ADSISearchResults.properties.manager) {
      $UsersManagerADSI = [ADSI]"LDAP://$($ADSISearchResults.properties.manager)"
      $row["Manager"] = $($UsersManagerADSI.properties.displayname)
      $row["Manager Mail"] = $($UsersManagerADSI.properties.mail)
    }
    $row["RDS Server"] = $($Session.ServerName)
    Switch ($Session.ColorDepth) {
      "4" { $ColorDepth = "16 bit" }
      default { $ColorDepth = $($Session.ColorDepth) }
    }
    $row["Used Resolution"] = "N/A"
    If ($Session.ResolutionWidth -ne 0) {
      $row["Used Resolution"] = "$($Session.ResolutionWidth)x$($Session.ResolutionHeight)@$($ColorDepth)"
    }
    $row["Login DateTime"] = $($SessionCreationTime)
    $row["Session State"] = "Disconnected"
    If ($($Session.SessionState) -eq "0") {
      $row["Session State"] = "Active"
    }
    $row["Cluster Name"] = $($RDSServer.ClusterName)
    $ConnectionsTable.Rows.Add($row) | Out-Null
    $TotalSessions++
  }
  $ProgressCount++
}
Write-Progress -Completed -Activity "Processing RD Servers from Connection Broker."
Write-Host "Total RDS Sessions registered are $($TotalSessions)"
$ConnectionsTable | Sort-Object -Property "User Account"
Posted in adsi, PowerShell, Remote Desktop Services, WMI.

Leave a Reply

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