Main Webpage


    Terminal Services Bulletin Board
    Links and Downloads
    Matthew Harris' Resume
    Contact the admin


    Disable the X box on the Terminal Services Client
    Change the client version of the Terminal Services Client
    Add the clock to the taskbar through the registry
    Make all processes appear in the Task Manager through a registry hack
    Prevent disconnects and stabilize your terminal services connection
    Fix your TSAdmin application when it becomes nonfunctional on the taskbar
    Disable/Enable all terminal services logons through the registry


    Restrict users to one session and reconnect them
    Share the redirected printer automatically
    Map your client's printer to an LPT port
    Rename client redirected printers
    Restrict users to only one terminal services session
    Automatically connect disconnected users back to their sessions
    Force software license compliance through a script
    How to reset all your TS sessions at once

Hard to Diagnose Problems

    Incorrect IE permissions can disable opening new IE windows

Only Allow One Logon Session Per User and Reconnect them to their Previous Session if possible

In this article, I'll discuss how you can use a batch script to restrict each user to have only one logon session. This script will also attempt to reconnect the user with their previous session if it still exists.

•The script, which can be downloaded here or at the end of this article.
•A terminal server that you have administrator access to.

For this tutorial, I'm going to step through the script to explain what happens.

Section 1: Variable declarations and headers:

            Set LoginNum=0
            Set LoginCount=0
            Set SessNum=-1

Basically, all I'm doing here is declaring some variables, setting their values, and forcing the script to localize all these variables within this script. Localizing the variables isn't absolutely necessary, but this helps to prevent variables from mixing up between your scripts, especially if you merge this script with other scripts.

Section 2: Query the terminal servers:

            For /f "skip=2 delims=* " %%i in ('qappsrv') do call :Next %%i
            If %LoginNum% LEQ 1 (EndLocal) && (Goto EoF)

This For command is where this script starts to get a little complicated. The For command starts the QAppSrv command, which creates a list of all terminal servers on the local network. For each of these terminal servers detected, a call is made to the Next loop (denoted by the :Next marker), which is discussed in Section 3 below. After the For command terminates, the If statement then checks if the user's total login count is greater than 1, which would mean they are logged in twice. If that count is 1 or less, then that means they aren't logged in twice, and in that case, the script terminates.

Section 3: Obtain a count to see how many times the user is logged in:

            Rem Checking the servers to see where the user is and update the count...
            For /f %%j in ('qwinsta /server:%1 ^| find /c /i " %UserName% "') do Set /A LoginNum=%LoginNum%+%%j
            Goto EoF

While this portion of the script is out of order, I've put it here just for this tutorial. I would encourage you to download the script to see the correct order of this script.
This Next loop takes a single terminal server's name and stores that value as %1. The For command queries that server (%1) using QWinsta and sends the output to the Find command. The Find command parses the output, searching for the user's name (%UserName%), and returns the count of how many times the user's name appears in the output. This count is then added to the LoginNum variable. The LoginNum variable is the running total of how many times the user is currently logged in. After this For command terminates, control is given back to the For command from Section 2. The For command from Section 2 then continues to call the Next loop, until all servers have been queried.

Section 4: Are they logged on twice on the local machine?:

            For /f "skip=1 tokens=3" %%i in ('qwinsta %UserName% ^| find /v ">"') Do set SessNum=%%i
            If %SessNum% EQU -1 (Call :Error 1) && (Goto EoF)

This For statement runs the QWinSta command on the local server to count how many sessions the current user has open locally. Ignoring the current session, if that count is valid, then that means the current user is logged in twice (or more) to the local machine. If this is the case, then the script will continue. Otherwise, if the user is only logged in once, then the script will end the localization of the variables and then exit; it is important to realize that while the user may have 2 or more active TS sessions in your farm, this script only works within the scope of the local machine, as we will see in the next step. If the current user has active sessions elsewhere in your TS farm, then the script will notify the user of this problem and terminate.

Section 5: Connect the user to their other session:

            If Exist %SystemRoot%\System32\TSCon.exe (TSCon.exe %SessNum%) Else (Connect.exe %SessNum%)
            If %ERRORLEVEL% NEQ 0 (Call :Error 2) && (Goto EoF)

This If statement checks to see what operating system you are running, since the connect command was renamed between Windows NT TSE and Windows 2000/2003. The Connect or TSCon utility is then run, which will connect the current session to the user's other session. The next If statement makes sure that the Connect or TSCon command succeeded.

Section 6: Cleanup before we exit:

            Goto EoF

            Rem This is bad, so warn the user, then log them off
            Msg %WinStationName% /W You are logged on at another server.  You need to log out of there before you can log in again.  (Error Code: %1)
            Goto EoF


If everything has completed successfully, then localization of variables is terminated, the current session which will now be in the disconnected state is logged off, and the script is terminated. The :Error portion of this section is called only if there is a problem with the script. In earlier sections, errors can occur, which will then call this :Error section which merely prints out an error message along with an error code to help admins debug where the error occurred. The :Error section is not normally called unless the script detects that a problem has occurred in processing variables or data.

Well, that's about it. You've just finished a walkthrough tutorial for this script. tutorial would be complete without a download, so here is the script in its entirety (compressed):