Monday, July 21, 2014

Terminal Server has exceeded max number of connections

I received a call requesting assistance one of our users is unable to remote into an SQL server. He is receiving the following error:

kb-terminal-max-connections

I tried to remote as well but received the same error. Then I started researching on how to find the users that are logged in, so that he may communicate with them and ask them to log off, but this brought a very limited amount of information. I found out that the class Win32_LoggedOnUsers doesn't really give you that information, but then I found out that there is a way to bypass the maximum number of connections by using the following command:

%systemroot%\system32\mstsc.exe /admin
Once I logged in I was able to go through the Task Manager and find and log off the extra user, but I was not happy with this solution. I feel like it might not always work. After further looking into this issue I found in Learn-PowerShell that I was able to use the WMI Class Win32_Process to get the Explorer.exe process and get the Owner, thus revealing the logged on users. 

Script found in sauce:
Function Get-WMIComputerSessions {
<#
.SYNOPSIS
    Retrieves tall user sessions from local or remote server/s
.DESCRIPTION
    Retrieves tall user sessions from local or remote server/s
.PARAMETER computer
    Name of computer/s to run session query against.
.NOTES
    Name: Get-WmiComputerSessions
    Author: Boe Prox
    DateCreated: 01Nov2010
.LINK
.EXAMPLE
Get-WmiComputerSessions -computer "server1"
Description
-----------
This command will query all current user sessions on 'server1'.
#>
[cmdletbinding(
    DefaultParameterSetName = 'session',
    ConfirmImpact = 'low'
)]
    Param(
        [Parameter(
            Mandatory = $True,
            Position = 0,
            ValueFromPipeline = $True)]
            [string[]]$computer
    )
Begin {
    #Create empty report
    $report = @()
    }
Process {
    #Iterate through collection of computers
    ForEach ($c in $computer) {
        #Get explorer.exe processes
        $proc = gwmi win32_process -computer $c -Filter "Name = 'explorer.exe'"
        #Go through collection of processes
        ForEach ($p in $proc) {
            $temp = "" | Select Computer, Domain, User
            $temp.computer = $c
            $temp.user = ($p.GetOwner()).User
            $temp.domain = ($p.GetOwner()).Domain
            $report += $temp
          }
        }
    }
End {
    $report
    }
}

But I didn't quite need all this so I simply made a one line :

(gwmi win32_process -computer SERVERNAME -Filter "Name = 'explorer.exe'").GetOwner().User 

Now I am able to find out the users that are logged in without having to remote into the server. 

Hope this might help other people out there!