In Part One of this series, we looked at the basics of how Terminal Server uses the registry. In this article, we’ll examine at how applications use the registry in Terminal Server environments, mostly focusing on application installation issues.
Installing an application on a Windows server causes it to write data and save settings in both the HKLM and HKCU registry hives. As we learned in the previous article, the HKLM hive stores the system-wide application settings such as file installation paths and installed options, and the HKCU hive stores the user-specific settings such as custom dictionaries, menu settings, and default fonts and colors.
As you’ve probably guessed, Terminal Servers behave a bit differently than regular Windows computers. To understand this, let’s look at an example. Imagine that you’re installing Microsoft Office onto a Windows XP workstation. Besides copying the files, the setup.exe program will write all the necessary Office settings to the registry. In this case, it will write the system-wide stuff to HKLM and it will write the default user settings to HKCU. On a single-user system such as Windows XP Professional, this works fine.
However, on multi-user Terminal Servers, this could cause a few problems. First is the fact that all the application’s new registry settings would be written to the specific HKCU of the actual user account that was used to install the application. This could cause a problem when a regular user logged onto the server and ran the application since their personal HKCU wouldn’t contain any of the application’s settings. (Whether this is a problem or not really depends on the application itself.)
So how does Terminal Server deal with these two problems?
Every user session on a Terminal Server operates in one of two modes: “execute” mode or “install” mode. Execute mode describes regular user session behavior when users are “executing” applications. This is the standard mode of operation and how your user sessions will operate 99.9% of the time.
However, when you install an application onto a Terminal Server, the session you’re installing it from switches to “install” mode. (In the old days, you had to manually put a session into install mode via the command-line switch “change user /install.” You can still do this in Windows 2003, although the server now is smart enough to detect when you’re installing applications and it automatically puts the session into install mode as needed.
So what’s the point of install mode?
Let’s think back to the application installation problem we outlined earlier. When an application is installed on a server, the application usually writes a bunch of settings to the active user’s HKCU hive. In a Terminal Server environment, there needs to be some way to ensure that any application settings written to HKCU when the application is installed get copied to every single user’s HKCU hive when they log in. Otherwise, applications might behave strangely for the users since they don’t have any of the proper registry keys configured.
Therefore, when a user session goes into install mode, the server monitors all the activity of that user’s HKCU hive. Then, any changes to the user’s HKCU\Software key (i.e. from the application installation) are also written to a special Terminal Server HKLM key at HKLM\Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software. This key is informally known as the “shadow” key. As such, this shadow key contains all the most recent application installation information that’s needed in each user’s personal HKCU\Software key.
So far, so good, right? The only thing missing is how a Terminal Server knows whether a user who’s logging on needs to receive some settings from the Terminal Server’s shadow area. It does this by comparing timestamps between the two.
When a session is in install mode, each time a “real” HKCU\Software value is echoed to the shadow key location the server updates a timestamp called “LatestRegistryKey” stored in the HKLM\ SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\IniFile Times. This value of this registry entry is the number of seconds since January 1, 1970.
(As a side note, you’ll also notice a listing of INI files with timestamps in this same registry location since install mode also affects them. However, in today’s world, INI files aren’t really used and we only really care about the registry operations.)
All these timestamp values live in that “IniFile Times” registry key mentioned earlier. One of the lesser-known facts about the Windows registry is that every registry key has its own timestamp that shows the last time it was updated, similar to standard file timestamps. (These timestamps apply to each key, not to each value.)
Anyway, whenever a user logs on to any Windows computer, a process called userinit.exe is used to run programs before the shell loads. In Terminal Server environments, this executable compares the hidden timestamp of the server’s IniFile Times key to a timestamp in the user’s HCKU hive that holds the last synchronization time. (This “per user” timestamp is stored in the user’s HKCU\Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\LastUserIniSyncTime.)
In doing so, the system can figure out whether the registry settings in the user’s HKCU are newer or whether the “shadow” settings in the server’s HKLM are newer. If the hidden timestamp of the IniFile Times key in the shadow area is more recent, the system knows that new software must have been installed on the server. Therefore, userinit.exe enumerates all the keys in the Terminal Server compatibility shadow are and compares each one’s hidden timestamp to the corresponding key in the user’s personal HKCU\Software key. If the shadow key is newer, the user’s corresponding key is deleted, and they receive the new key from the shadow area once their sessions starts. (This is known as “Terminal Server registry mapping.”
On the surface, it seems like this architecture is rather ingenious and that you don’t have to worry about anything. However, there is one major problem that can manifest itself in the real world.
Imagine that you have multiple Terminal Servers or Citrix servers that are all running the same application, such as Microsoft Office. If you’re like most companies, you probably installed Office on those servers a several months or even years ago. Since Office was originally installed via a user session operating in install mode, the server’s shadow key was created and timestamped with the original install time. Any users who did not have the appropriate Office settings in their own personal HKCU key received them when they logged on to the server for the first time.
Now, fast forward to today. What happens if you want to add more capacity to your server farm? Most likely you’d build a few more servers, install Office on them, and load-balance them with your existing servers.
Can you see the problem here? The timestamp on the shadow key area of the new Terminal Servers will be current, and in fact much newer than each user’s individual HKCU last update timestamp. Therefore, upon logging on to one of the new servers, userinit.exe will start comparing the key-by-key timestamps of all the HCKU\Software keys to the server’s shadow area software keys. Since the server just got a fresh install of Microsoft Office, those timestamps will be much newer than any of the user’s personalized settings in their own HKCU. The result? Mass deletion of all the Microsoft Office-specific keys in the user’s HKCU\Software hive.
From the user’s standpoint, it will appear as if all of their Office settings reverted back to the defaults, all because they were randomly load-balanced to a new Terminal Server.
So what can we do to change this behavior? Unfortunately, there’s no way to disable the shadow key functionality, and Windows 2003 does a pretty good job of ensuring that applications are installed with the user session configured for install mode. Therefore, if we can’t disable it, we’ll have to outsmart it.
This essentially means that we’ll have to ensure that the timestamps on the servers’ shadow area are older than the timestamps of the user’s HKCU hive. There are two ways to do this:
- Before installing an application, set the server’s system clock back to before the time you installed the application on one of the original servers.
- Deploy the new server from an image of the old server. (Ghost, sysprep, breaking a hardware mirror, etc.) If you do this, remember that you must use some kind of imaging technology. Unattended installs will not work in this case since they’ll write the current dates to the shadow area.
Alternately, if you don’t want to do either of these, you can simply delete the keys out of the new server’s shadow area. That will ensure that the users’ versions of those keys are not deleted when they log on to a new server. However, if you do this, you’ll have to use a logon script or some other method to ensure that new users get the appropriate keys populated into their own HKCU hive.
That pretty much sums up what you need to know about how the registry is used when you install applications. In the final installment of this three-part series on the registry, I’ll look at all the specific registry keys that are important in Terminal Server environments.