Thought I would post a couple of PowerShell scripts that I’ve recently written. Both of these scripts were written specifically for terminal servers but they can be modified as needed. The first one finds what terminal servers a user is logged into. It retrieves a list of terminal server names from the specified OU. I started out by using the Get-TSServers cmdlet for the list of servers, but that cmdlet takes a while and you have more control by just using the Get-ADComputer cmdlet since your terminal servers are more than likely in their own OU anyway. You need to use a For-Each loop since you can’t specify multiple computer names with the Get-TSSession cmdlet. Looking at the help for that cmdlet shows that all three parameter sets start with: Get-TSSession [-ComputerName <String>]. If it showed: Get-TSSession [-ComputerName <String[]>] instead, multiple computer names would be able to be entered and there would be no need for the For-Each loop.
#Prerequisites:
#Download and install the “Terminal Services PowerShell Module” (by Shay Levy)
#For Windows 7, Download and install the “Remote Server Administration Tools”
#Enable the “Active Directory Module for Windows PowerShell” feature
1 2 3 4 5 6 7 | Import-Module ActiveDirectory Import-Module PSTerminalServices $user = Read-Host "Enter a user name" $servers = Get-ADComputer -Filter * -SearchBase "ou=terminal servers,ou=computers,ou=test,dc=mikefrobbins,dc=com" | Select-Object -ExpandProperty Name ForEach ($server in $servers) { Get-TSSession -ComputerName $server -Username $user } |
This second one finds who is running a specific process on the terminal servers such as “msaccess.exe” (Microsoft Access). It could actually be used for any machine that supports PowerShell since it doesn’t contain any cmdlets that are specific to terminal server. This example also demonstrates how to change the column header names.
#Prerequisites:
#For Windows 7, Download and install the “Remote Server Administration Tools”
#Enable the “Active Directory Module for Windows PowerShell” feature
1 2 3 4 | Import-Module ActiveDirectory $process = Read-Host "Enter a process name" $servers = Get-ADComputer -Filter * -SearchBase "ou=terminal servers,ou=computers,ou=test,dc=mikefrobbins,dc=com" | Select-Object -ExpandProperty Name get-wmiobject win32_process -computer $servers | where {$_.name -eq $process} | select @{l='Server';e={$_.__server}}, @{l='User';e={$_.getowner().user}}, @{l='Process';e={$_.name}} | sort Server, User |
Here’s an updated version of the second script based on Jeffery Hicks comments:
1 2 3 4 | Import-Module ActiveDirectory $process = Read-Host "Enter a process name" $servers = Get-ADComputer -Filter * -SearchBase "ou=terminal servers,ou=computers,ou=test,dc=mikefrobbins,dc=com" | Select-Object -ExpandProperty Name get-wmiobject win32_process -filter "name='$process'" -computer $servers | select @{l='Server';e={$_.__server}}, @{l='User';e={$_.getowner().user}}, @{l='Process';e={$_.name}} | sort Server, User |
µ
Suggestion for WMI queries: Take advantage of WMI filtering.
get-wmiobject win32_process -filter “name=’$process'” | Select …
This is faster as objects are filtered as they are assembled. In your setup ALL process objects are returned and then filtered. You always want to filter as far to the left of your expression as you can.
Have you tried writing a wrapper around the ‘query.exe’ command?
Query session /server:ts01
You can also disconnect sessions via the ‘reset.exe’ command.
reset session
Would make for some nice pipe-lining.
Mr. Robbins,
This is a great post and has saved me a couple hours of banging my head with trying to use Get-TSSESSION against multiple servers. I was just trying to use a $servers variable and GET_CONTENT to iterate through a server list text file. I could not get it to work until I found your post on using the ForEach method. Thank you!!
I took your method and modified it to only query each terminal server to show the ACTIVE sessions but the output is ugly with no line seperation between each server.
Is there a way in my script I could echo a line seperator between each server output? See below for an example…..
Thank you for your help.
Rob
SCRIPT – – – –
$servers = Get-Content -Path C:Load_StuffMonitoringScriptsTS_list.txt
ForEach ($server in $servers) {Get-TSSession -ComputerName $server -state ACTIVE }
OUTPUT – UGLY – – – –
PS C:Load_StuffMonitoringScriptsPowerShell> .GetActiveSessionList.ps1
Server SessionID State IPAddress ClientName WindowStationName UserName
—— ——— —– ——— ———- —————– ——–
ts01.LOAD.LOCAL 3 Active 10.4.13.149 AT2RIGHT-0015 RDP-Tcp#7 LOADUser3.2.4_0015
ts01.LOAD.LOCAL 4 Active 10.4.13.187 AT2RIGHT-0025 RDP-Tcp#23 LOADUser3.2.4_0025
ts02.LOAD.LOCAL 6 Active 10.4.13.177 AT2RIGHT-0038 RDP-Tcp#9 LOADUser3.2.4_0038
ts02.LOAD.LOCAL 7 Active 10.4.13.209 AT2RIGHT-0049 RDP-Tcp#6 LOADUser3.2.4_0049
I would like to see something like this to make it easier to read…..
PS C:Load_StuffMonitoringScriptsPowerShell> .GetActiveSessionList.ps1
Server SessionID State IPAddress ClientName WindowStationName UserName
—— ——— —– ——— ———- —————– ——–
ts01.LOAD.LOCAL 3 Active 10.4.13.149 AT2RIGHT-0015 RDP-Tcp#7 LOADUser3.2.4_0015
ts01.LOAD.LOCAL 4 Active 10.4.13.187 AT2RIGHT-0025 RDP-Tcp#23 LOADUser3.2.4_0025
******************************************************************************************************************
ts02.LOAD.LOCAL 6 Active 10.4.13.177 AT2RIGHT-0038 RDP-Tcp#9 LOADUser3.2.4_0038
ts02.LOAD.LOCAL 7 Active 10.4.13.209 AT2RIGHT-0049 RDP-Tcp#6 LOADUser3.2.4_0049
I know this is very late, but for anyone else looking for an answer, Format-Table is your friend 🙂 Check out some guidance here: http://www.computerperformance.co.uk/powershell/powershell_format_table.htm
Hi Robin,
Greetings,
Frankly speaking, I have no knowledge in scripting.
My requirement is to fetch all the Terminal Server hostnames in my Infrastructure. Please could you share me a script which can do the needful.
Thanks a lot for your help.
Regards,
Prem Ananthu Ananthu
Environment: Windows Server 2003, Windows Server 2008 and Windows Server 2008, R2