Making your application Terminal Services friendly

Posted: (EET/GMT+2)

 

Making your application Terminal Services friendly

Feb 25, 2001

Windows 2000 with Terminal Services
Optional: Borland Delphi 5

With the increasing need for server-based computing, the demand for Windows Terminal Services and Citrix Metaframe is booming. In the server-based computing metaphor, every application is running on the server instead on the client computer. If you are building applications for large corporations or ASPs, you must make sure your application behaves nicely in a Terminal Services environment.

When your application is running on Windows 2000 Terminal Server or Citrix MetaFrame environment on Windows 2000, your application will run only on the server. The client computer acts just like a dump terminal, transferring only mouse and keyboard to the server and displaying the UI.

Because the server is potentially running tens of applications at the same time, you definitely need to optimize your application for this environment. For example, if your application is using threads to efficiently use the CPU resources, it might work perfectly well on the standalone client computer. However, when running on a server, potentially many instances of your application could be running, resulting in a performance catastrophe.

Detecting Terminal Services

The first step in becoming Terminal Server (TS) friendly is to detect whether TS has been installed. On Windows 2000, this can be detected by reading the system registry - there doesn't appear to be any APIs for this purpose. The registry key your application needs to read is:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ProductOptions\ProductSuite

This key is of type REG_MULTI_SZ, meaning that potentially multiple zero-terminated strings can exist in the value. For instance, if your using Borland Delphi to build your applications, you cannot use the regular TRegistry class to read the value. Instead, you must use a custom-made version of the TRegistry class, available in the download section. If Terminal Services are installed on the computer, the key value includes the string "Terminal Server".

registry editor

Remember that detecting if terminal services are installed is not enough. Instead, you must be able to detect if your application is running inside a terminal server session. This can be achieved with the following code in Delphi:

Function IsRemoteSession : Boolean;
Const sm_RemoteSession = $1000; { from WinUser.h }
Begin
  Result := (GetSystemMetrics(sm_RemoteSession) <> 0);
End;

Note that the above code works only in Windows 2000 or later. Also, the original constant SM_REMOTESESSION is not defined in Delphi's interface files.

Terminal Server APIs

If you want to take good use of Terminal Services, you should concentrate on the Terminal Server APIs. These are documented in the latest Platform SDK by Microsoft, available from the MSDN website. The sad thing about Delphi is that it doesn't have all required headers translated (remember, Delphi 5 doesn't officially support Windows 2000).

However, the Project JEDI has translated the TS APIs, and you can download the translated header files from their site. After downloading the headers (or translating your own), you can start to use the APIs, for instance WTSQuerySessionInformation or WTSSendMessage.

Using these APIs is beyond the scope of this article, but you can find all the needed documentation on MSDN.

Download the example code

Download makingyourapplicationterminalservicesfriendly.zip (2 kB) which contains the sample TMultiSZRegistry class that can handle MULTI_SZ strings in registry keys. Please note that the sample application will require Delphi 5 or later.

* * *

Need help making your application TS aware? Let us know!