Managing User Specific Application Configuration Data in a Terminal Service Environment
Writing to the Registry
Today, we pretty much take for granted that when a Windows application is installed that information related to the application is written to the Windows registry. The practice is so common, in fact, that most administrators really don’t even care what data the application’s installer is writing to the registry, so long as the application works and it doesn’t break anything else in the process.
Microsoft has laid out very specific guidelines for developers as to how application data should be written to the registry during application installation. Of course we all know that programmers don’t always play by the rules. An application’s logistics might prevent the developer from using the recommended best practices, or the developer might be ignorant of the proper way to store application data in the registry, or the developer might just be pressed for time or take the lazy way out. Whatever the reason, there are lots of applications out there that store data in improper locations within the registry. In most cases, nobody really cares, and the misuse of the registry doesn’t really hurt anything. This all changes if the application is to be run in a Terminal Service environment though.
If an application is going to be run through the Terminal Services, it is crucially important that the application’s data be stored in the correct portion of the registry. Normally, when you install a properly written application, the application differentiates between computer specific data and user specific data. Computer specific information is usually written to the HKEY_LOCAL_MACHINE (HKLM) portion of the registry. User specific data on the other hand is typically written to HKEY_CURRENT_USER (HKCU).
So what does all of this have to do with the Terminal Services? Well, I have seen quite a few applications that save all of the application’s configuration data to HKLM rather than segmenting the data into computer specific and user specific data. On a standalone machine, this usually isn’t a problem, but it can have some interesting side effects in a Terminal Service environment.
To see why this is the case, let’s look at an application that we are all very familiar with; Internet Explorer. Internet Explorer, as we all know, is a Microsoft product and as such it is coded properly. For the sake of demonstration though, let’s pretend that Internet Explorer was written in such a way that all of its configuration data was stored in the HKLM portion of the Windows registry.
On a standalone machine with a single user, this method of storing data in the registry probably wouldn’t cause any problems. That changes if you are running Internet Explorer through the Terminal Services though. Let’s pretend that a user (we will call this user User A) wanted to add a Web site to their list of favorites. Internet Explorer would allow User A to add the site to their favorites list, no problem. Let’s pretend that now another user (I will call them User B) logs in through a completely different Terminal Service session and needs to use Internet Explorer. User B begins browsing the Web and soon discovers a site that they want to add to their favorites. User B goes to add the site to the favorites list and sees that there is already a site on the favorites list that was put there by User A. Of course User B doesn’t realize that the site that they see on their favorites list was put there by User A. Therefore, they just delete the site from the list and add their own site. Later, when User A logs back in, the site that they added to the favorites is gone, but User B’s site is showing up on the favorites list.
Another interesting side effect to the situation that I described above has to do with the fact that the HKLM registry key is machine specific. In organizations with a single terminal server, using a machine specific registry key isn’t a big deal. However, if you have multiple terminal servers in your organization, and applications store user data in HKLM, then the users will only have access to their configuration data for as long as they continue to log into the same terminal server. The minute that they log into a different terminal server, their configuration data appears to have vanished (in actuality it’s safe and sound on another server).
Hopefully by now, you get the point that storing user specific data in the HKLM portion of the registry is a bad thing in a Terminal Service environment. The problem is that you can’t really install configuration data into HKCU either. The reason is because HKCU applies only to the current user, not to every user who could potentially use the server.
The trick to installing applications in a way that allows them to be shared effectively among multiple users in a Terminal Services environment is to take advantage of the Terminal Services two modes of operation. A Terminal Service session can be run in either Execute mode or in Install mode. You can technically install applications while running in either mode, but you will get very different results depending on your session mode.
Execute mode is a Terminal Service session’s default operating mode. If you install an application while running under execute mode, then the application will be installed in exactly the same manner as it would if you installed it onto a stand alone computer. This means that the application’s Setup program will make direct edits to the HKLM and HKCU portions of the registry.
As you have probably already figured out, Install mode is designed specifically for installing applications. When you install an application while running in Install mode, the Setup program will write registry data directly to HKLM and to HKCU just as it would in a stand alone environment. The difference is that any registry entries that are written to HKLM or HKCU are shadowed to HKLM/Software/Microsoft/Windows NT/CurrentVersion\TerminalServer\Install.
OK, so let’s say that you install an application while running in Install mode. Let’s take a look at what happens when User A tries to run the application. When User A attempts to run the application, Windows will notice that some critical registry keys are missing from HKCU. Since Windows can’t find the necessary registry keys in HKCU, it looks in HKLM/Software/Microsoft/Windows NT/CurrentVersion\TerminalServer\Install. Assuming that the necessary registry keys exist in this location (they should), they are copied to HKCU. Many applications also depend on user specific INI or DLL files. If the application depends on such files, the files are automatically copied either to the user’s home directory or to the user’s profile directory if no home directory exists.
So what does all of this mean in plain English? It means that when the application is initially installed, it is setup in a way that creates a generic set of configuration data for the application. The first time that each user accesses the application, the generic configuration data is copied to that user’s portion of the registry so that the user can customize the application to their own taste. Keep in mind that a user’s configuration for an application does not return to a clean and pristine state when the user logs out. The user’s configuration for that application is saved so that it will be available from one session to the next.
So I guess the million dollar question now is how do you run a Terminal Service session in Install mode? It’s actually a lot easier than you think. Every Terminal Session starts out as an Execute mode session. However, you can switch to Install mode by simply using the Add / Remove Programs applet in the Control Panel to install an application. In fact, the Terminal Services in Windows Server 2003 even have a safe guard in place. If an application’s Setup program is named Setup.exe, then Windows will not let you run Setup directly. It forces you to go through the Add / Remove Programs Control Panel applet if you want to install the application. If the application’s Setup program is named something other than SETUP.EXE, then the application can be installed either in execute or in install mode.
In this article, I have explained that the way that applications make use of the Windows registry can really throw a monkey wrench into the Terminal Services. I then went on to explain that you can get around these issues by installing applications in Install mode rather than in Execute mode.