SolutionBase: Tuning applications for the Terminal Services

You can save a lot of expense on end-user workstations by deploying Terminal Services. The problem is, applications don't always work efficiently under Terminal Services. Here's how to tweak applications for maximum performance.

Over the last couple of years, thin client computing has been gaining rapid popularity. Part of this is because thin client networks lower administrative overhead and generally improve security. Another reason for the more recent popularity gains has to do with the fact that the availability of high-speed processors has finally made thin client computing practical. In spite of the fact that today's processors are capable of running at such high speeds, it is still important to do some planning and fine tuning where applications are concerned so that you can make the most of the server's available resources. In this article, I will discuss some of the issues that you should consider prior to deploying applications in a thin client environment. I will then go on to show you some tricks to make those applications perform more efficiently.

Before I begin

Before I get started, I want to point out that this article assumes that your terminal server is running the 32-bit version of Windows Server 2003. Some of the things ideas and techniques that I will be discussing would be incorrect in a 64-bit environment.

16-bit applications

The best advice that I can give you in regards to 16-bit applications is that if at all possible, you should refrain from using them. I know that this is impossible in some cases though. For example, I have a friend who works for a large insurance company. The company is still running DOS based applications that were coded in Clipper about twelve years ago. The company can't replace the applications because they are proprietary. They were developed in house and none of the programmers who developed those applications work for the company today. Therefore, the majority of the company's mission critical data is tied to an ancient application that nobody seems to know how to update.

If you are in a situation like that, and you really need to run the application in a thin client environment, then doing so might be possible, but be prepared to pay the price. There are several reasons why it isn't advisable to run a 16-bit DOS application in a thin client environment.

The first reason is that Windows Server 2003 doesn't natively run 16-bit DOS applications. It will run them, but in order to do so, the server has to run the application within a virtual machine. This virtual machine emulates a 16-bit operating system. I don't want to get into all of the technical details of how this emulation works, but let's just say that because of this emulation, running a 16-bit DOS application usually requires more CPU time and memory than a comparable 32-bit application would.

Another reason why it isn't advisable to run DOS applications in a thin client environment is because many DOS applications are not designed to be run simultaneously by multiple users. Let's take that proprietary application that the insurance company is using as an example. The application itself is simply a front end to a database. I have absolutely no idea what type of database is on the backend, but I can tell you that some of the older databases could only be accessed by one person at a time. If two people tried to access the database simultaneously, and the application didn't have a locking mechanism to prevent such an action, data corruption could occur. If you are thinking of running a DOS based application in a terminal service environment, I very strongly recommend doing a little research to determine if any harm can come from having multiple people use the application simultaneously.

The third reason for avoiding DOS applications is because DOS was not a multitasking operating system. When a developer coded a DOS application, it was usually a safe assumption that with the possible exception of a TSR (terminate and stay resident application) the application would have exclusive use of the system. Because of this, most DOS applications do not do anything to prevent the application from using all of the system's resources. A classic example of this is that some DOS programs use a command called INKEY$ to constantly poll the keyboard for input. This constant polling burns up a lot of CPU cycles. Now, imagine what would happen if 20 people were running such an application at the same time.

Unfortunately, there isn't a lot that you can do to make DOS applications behave well within a Terminal Service environment. Most DOS applications will run under the Terminal Services though as long as they don't exploit unusual graphics modes or require strange memory configurations. If you are stuck using a DOS application, the best advice that I can give you is to run the application in text mode if at all possible. Remember that the DOS operating system wasn't designed to where you have one graphics driver and all of your applications use that driver. Instead, each application has its own individual collection of drivers. Therefore, a graphics configuration that works perfectly for one system will be completely inappropriate for another system. Since DOS applications don't write configuration data to the Windows registry, you might be stuck trying to find a configuration for the application that works for everyone.

Some DOS applications store configuration application within a .CFG file. If you have such an application, you might be able to tweak the application so that it stores the .CFG file in a user specific location (such as in each user's home directory). If you can pull this off then you will be able to create a separate configuration for each user.

32-bit applications

Now, I want to turn my attention to regular, 32-bit Windows applications. When it comes to a thin client environment, not all 32-bit applications are created equally.

Generally speaking, 32-bit Windows applications aren't really subject to the same types of problems as DOS applications. There are exceptions to every rule, but you usually won't have to worry too much about a 32-bit Windows application running away with the system resources because most developers assume that the application will have to share system resources with other Windows applications, and design the applications accordingly.

The biggest problem with 32-bit Windows applications tends to stem from the fact that many Windows applications aren't designed to be run in a thin client environment and therefore do not store user specific information in an appropriate manner. As you may know, the Windows registry stores user specific data in a separate area from computer specific data. The problem is that many applications that are not specifically designed to support multiple users store all of the data related to that application within the machine specific section of the registry.

Specifically, all of the user specific configuration information related to an application should be stored in the HKEY_CURRENT_USER (HKCU) portion of the registry. Machine specific configuration information related to an application is usually stored in the HKEY_LOCAL_MACHINE (HKLM) registry hive.

So what does it matter which registry hive an application stores configuration information in? To illustrate the problems associated with incorrect usage of the system's registry, I want to use an application that everybody is familiar with; Internet Explorer. In real life, Internet Explorer stores user specific configuration data as a part of the user's profile, which is perfectly acceptable. For illustration purposes though, let's pretend that Internet Explorer is an application that you have to install separately from Windows and that it stores all of its configuration related data in the HKLM portion of the registry.

The first time that a user logs in and uses Internet Explorer, everything will be pretty much normal for the user. In fact, odds are pretty good that the user will be completely oblivious to any problems. Now, let's pretend that while the user is logged on they visit a couple of random Web sites and add those sites to their favorites list.

Now, another user logs on from a different computer and opens Internet Explorer. They stumble onto a cool Web site and go to add the site to their favorites. What's this though? The Favorites list already contains a few Web sites. Since the user didn't put those items into the favorites, they delete them and then add in their own favorites. As you can see, the problem is that when user specific information is stored in the HKLM portion of the registry, anyone who logs in shares the same configuration and can overwrite each other's configuration at will. In the above example, if Internet Explorer had used the HKCU portion of the registry to store user specific data then each user would have their own Favorites list and would not be able to see or modify other user's favorites.

This does bring up an interesting point though. Suppose for a moment that an application is designed correctly and stores user specific configuration data in the HKCU section of the system registry. If you've got multiple users, you may be wondering how this configuration data gets in to the HKCU portion of the registry without you having to manually configure the application for each user.

To answer this question, you have to understand a little bit about how the Terminal Services operates. The Terminal Services can run under two different modes; Execute Mode and install mode. Any time that users log into the Terminal Services, they are running in Execute Mode. However, if you are attempting to install a new application, you can log into the Terminal Services through Install Mode. When you install a new application in install mode, then any settings that are added to HLCU are also written to the HKLM portion of the registry.

When a user runs the application for the first time, that user doesn't have any configuration data related to that application in the HKCU portion of the system registry. Since the application is lacking some of the required configuration data, the configuration settings are copied from HKLM to HKCU. Once the data exists in HKCU, then it can be customized for the individual user if necessary. Any data copied to HKCU is permanently so that configuration data will not have to be copied from HKLM the next time that the user logs in.

Tuning applications for the Terminal Services

Now that I have talked about some of the issues that you may encounter when running an application in a Terminal Server session, I want to get down to business and talk about tuning an application so that it runs optimally in your thin client environment. I will be honest with you. There are lots of ways that you can tune applications and there is no way that I could possibly address them all within the confines of a single article. Therefore, I want to focus most of my attention on tuning applications through the application install mode that I mentioned earlier.

Tuning an application through install mode is an effective technique because all of the user's initial configuration settings will be based on the settings that you provide through install mode. Therefore, if you fine tune an application at the time of installation, then your users will be running a copy of the application that you have already optimized for your environment.

Since we are going to be optimizing applications through install mode, the first question that I want to address is how you can get into install mode. When you log into the Terminal Services, you will be running in Execute Mode by default. If you try to install an application while running in Execute Mode, a couple of things can happen. If you are using Windows Server 2003, and the application's installation program is named SETUP.EXE, then Windows will block you from installing the application. Instead, you will be instructed to install the application by using the Add/Remove Programs applet in the Control Panel. Using the Add/Remove Programs applet forces the application to be installed in install mode.

If the application's installation program is named something other than SETUP.EXE, then Windows won't force you to use the Add/Remove Programs applet. However, if you do manage to install the application outside of Add/Remove Programs, the application will have been installed in Execute Mode and won't be properly shared among other users.

You can also use a built in, command line utility called CHANGE USER to switch modes. If you enter the CHANGE USER /QUERY command, Windows will tell you which mode you are running in. You can the switch between install and Execute Mode by using the CHANGE USER command with the /EXECUTE or the /INSTALL switches.

OK, so you have switched your session into Install mode and are installing an application. You are probably wondering what types of things you can do to make the application better suited to the thin client environment. The first thing that I recommend doing is disabling any features that will consume needless resources.

You might have to use a little imagination when deciding which features to disable. For example, if you are installing Microsoft Office, there probably isn't anything obvious that you can shut down to preserve system resources. However, Office applications are designed to check spelling and grammar as you type. This "on the fly" proof reading consumes more CPU resources than most people realize. On a stand-alone system, it's no big deal to use these features, but you can save a significant amount of processing power on your server by disabling on the fly proofing.

Another thing that you can do to save yourself some work later on is to customize the paths to which data is saved. I'm not talking about the location within the registry where configuration data is saved, but rather the location that data from the application is saved to. For example, suppose that you had an application that was designed to save data by default to C:\Program Files\application\data. This location would work fine if the application was running in a standalone environment, but it causes problems in a Terminal Service environment. Odds are that users would not even have rights to the C:\Program Files\application\data folder. Even if the users did have rights to this folder though, you would run into the problem of everybody being able to access everyone else's data.

A better solution is to change the application's data output path while you are setting up the application. In doing so, you will usually want to stay away from static paths unless you specifically need for everyone to share the data within a common folder. Instead, you would want to direct the application to save data in the user's home folder. To do so, you could enter the path to include the user's name as a variable. For example, a path to the user's home directory might look like \\servername\users\%username%\data.

If for some reason your application doesn't allow you to use universal naming conventions or environment variables within the data output path, you could just direct the output to a mapped drive. For example, you could just tell the application to save all data to H:. In the mean time, you have used a login script to map H: to \\servername\users\%username%\data.