SMClient: Microsoft's Automated Terminal Services Client

Smclient.exe, formally named "Terminal Server Client Simulation", is a tool designed for simple simulation of multiple client connections to a Terminal Server.

Like many testing and simulation tools, however, its usability goes far beyond the original design goal.  Smclient enables automated logon/logoff/disconnect, with activity which can be controlled by a decently-sized scripting language.  Since it displays the mstsc.exe GUI, you can even start a session and intervene.  It has some excellent verbose debugging options, so running it while attempting to connect to a remote system will allow you to do some nice diagnostics.

How Do I Get SMClient?

If you have the Windows 2000 Server Resource Kit, you already have it.  You can download an updated version along with several other goodies from Microsoft's Terminal Server Capacity Planning Tools site.

If you don't have the Resource Kit, you can download smclient from Microsoft's FTP server.

What files do I need?

Depending on what package you have, there may be significant variations in the particular files and the versions.  The crucial files we need are the following:

Configuring SMClient's Execution Environment

A couple of things are necessary here. 

First, smclient.ini must be in your working directory; if you have it in the same path as smclient.exe, change to that path before executing. 

tclient.dll must be in the same location as well.

Adapting SMClient.ini

I had to make a few modifications to the default file to make it correctly perform an autologon. You can download my version of smclient.ini for reference or direct use.

Running SMClient

There are several command line options for smclient.  Here's an example with some of my preferred options:

smclient -f:C:\tmp\smscript.txt -s:192.168.1.41 -l:1 -v -d

"-f:<filename>" specifies the path to the script you want to run.

"-s:<ip-or-servername>" allows you set the server you will be remoting to.  It can also be specified in the smclient.ini file; if you spec it on the command line, though, servers listed in the INI file will be ignored.

"-l:1" tells smclient to loop through the script only once ( an argument of "0" will make it loop continuously).

"-v" makes smclient give verbose feedback in its console window

"-d" turns on debug message display.

Scripting SMClient

General Structure

The scripts used by smclient have a C-ish syntax.  Generally, a script will be wrapped up in a job tag like this

job
{

}

You will typically start with a "connect" and end with a "logoff" or "disconnect".  You can freely insert comments which are (like in C) preceded with a double forward slash:

// This is a comment and will be ignored by the script parser

A Simple Session Script

Let's put together a simple script that logs on, runs a command, then logs off. 

First, we need to provide connection details with the connect command.   The details provided are username, password, domain, client width, and client height.  If you are not logging on to a domain, you supply an empty argument.  The command looks like this:

connect ( "MyName", "LetMeIn", "", 800, 600);

 Now we want to run Notepad as soon as we log on.  To start a shell application, we use the start command; it takes one parameter, which is the command line for the application.

start("notepad");

Usually smclient seems capable of stacking commands and running them only after it is possible to do so, but it can occasionally be quirky about this.  The scripting language includes a sleep command which takes an argument in milliseconds; to give us time to see the interface, we're going to put in a 2-second sleep next:

sleep(2000);

We can send raw text to the session with the sendtext command.  This will go to whatever has the focus.  Sendtext takes a second parameter, which specifies the number of milliseconds to wait between sending characters.  Since notepad was just launched, we would expect any text we send to appear in it.

sendtext("Jackdaws love my big sphinx of quartz.", 25);

We can send specific keystrokes and mouse events using the senddata command.  The senddata command has 3 parameters: a message name , and the wparam and lparam values for the message.  Here's how we send an "Enter" keystroke; note that it takes two data transactions, one for mousedown and one for mouseup:

senddata("WM_KEYDOWN", 13, 1835009);
senddata("WM_KEYUP", 13, -1071906815);

Let's do another 2-second pause and send a short piece of text:

sleep(2000);
sendtext("Tippecanoe and Tyler, too!");

and then sleep for a couple of seconds:

sleep(2000);

Finally, we can disconnect our session:

disconnect();

Altogether, our script looks like this:

job
{
 connect ( "MyName", "LetMeIn", "", 800, 600);
  start("notepad");
  sleep(2000);
  sendtext("Jackdaws love my big sphinx of quartz.", 25);
  senddata("WM_KEYDOWN", 13, 1835009);
  senddata("WM_KEYUP", 13, -1071906815);
  sleep(2000);
  sendtext("Tippecanoe and Tyler, too!");
  sleep(2000);
 disconnect();
}

Other Notes on SMClient Sessions

There is much more to the client than this; unfortunately, the documentation is exceedingly sparse so we have to learn about the client by observation.

Console Data

If you observe the console window in which smclient is running, you will see that essentially every piece of text displayed anywhere is being echoed.  Data from the server is shown as "Received"; data being sent to the server is "sent".

 You will also notice the distinct thread IDs for each type of transaction.  These are the actual messages being sent and received by the Terminal Services Client's Sender and Receiver threads. (The third client thread, the Interface thread, handles the GUI and thus is text-impaired).

Senddata Messages

There are a few senddata commands to be seen in the smclient.doc - very few.  There is no need for a TS reference on the messages, though; the senddata messages are the keyboard input messages and mouse input messages documented in the Platform SDK documentation on the Windows User Interface.