I need to find an easy way to kick off teammates from a server if they forget to log out. Our terminal service has a limit of 2 connections. I wrote the following function to get the logged in users. As I understand in powershell 2 there are nicer ways to do this but I am stuck with version 1 for now.
The following function will get me the logins per server. (If you know a prettier way to do this feel free to educate me. :) I am not happy with the func and hoping learn a few tricks from you.)
function get-terminal-users($serverName)
{
$path = "C:\ntui\source\i386"
cd -path $path
$result = invoke-expression -Command ".\quser.exe /SERVER:$serverName" | select -Skip 1
$a = @()
foreach($row in $result)
{
$d = new-object Object
$columns = $row.Replace(" ", " ").Split(" ") | ? {$_ -ne ""}
$d | add-member -membertype noteproperty -name UserName -value $columns[0]
$id = -1
$sessionName = ""
$columShift = 0
#this part was not ok and needed fixing. Thanks Winfred for the answer!
if([system.int32]::tryparse($columns[1].ToString(),[ref] $id))
{
$columShift --
}
else
{
$sessionName = $columns[1]
$id = [system.int32]::parse($columns[2].ToString())
}
$time = [DateTime]::Parse($columns[5 + $columShift] + " " + $columns[6 + $columShift])
$d | add-member -membertype noteproperty -name SessionName -value $sessionName
$d | add-member -membertype noteproperty -name ID -value $id
$d | add-member -membertype noteproperty -name State -value $columns[3 + $columShift]
$d | add-member -membertype noteproperty -name Idle -value $columns[4 + $columShift]
$d | add-member -membertype noteproperty -name Time -value $time
$a += $d
}
return $a
}
So I need the list if users and then I have to kick one guy out if the connection count is higher than the allowed maximum. If you know a way to get this info from the server I would really appreciate your help.
$name = "myserver"
$maxConnections = 2
$users = get-terminal-users($name)
if($users.Count -eq $maxConnections)
{
$idList = $users | ? { $_.State -eq "Disc" } | select -First 1 | foreach { $_.ID }
foreach($id in $idList)
{
invoke-expression -Command ".\logoff.exe /SERVER:$name $id -V"
}
}
The issue is that I can only interact with Active connections. Abandoned connections are still use up the available connections and I don't seem to be able to do much about them. A user with a Disc status seems to use up a terminal connection and when I call logoff on its id for some reason a local process is terminated. Is there a way to get rid of Disc connections?
rwinsta.exe also seems to only work with active connections.
I am running the script on XP and targeting a Win 2003 server.
You add the $id incorrectly to the custom object at this line:
$d | add-member -membertype noteproperty -name ID -value $id
Disconnected sessions don't have a session name see:
quser.exe /SERVER:mycomputer
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
winfred 2 Disc 4+21:05 2/28/2012 8:38 AM
And require the $columShift, which you have on all your properties, except on the ID Noteproperty. Because of that, you specify the ID incorrectly to logoff.exe, when you are trying to log off a disconnected session.
Instead that line should be:
$d | add-member -membertype noteproperty -name ID -value $columns[2 + $columShift]