Terminal server application compatibility scripts have been around for a long time – so long in fact, that I considered them a legacy and stowed away any knowledge of them in a very remote area of my brain. When a Citrix customer brought up a problem with the mapping of ROOTDRIVE in the User Profile Manager forum, at first I had no clue what he was talking about. Luckily, the customer was able to pin the problem down to a specific command that failed when, and only when, User Profile Manager was processing the logon. This is the story of UsrLogon.cmd, ACRegL.exe and UPM.
Application Compatibility Scripts … WHAT?
Back in the old days, when you had to get a special edition of NT4 if you wanted to deploy terminal services, application compatibility issues were dealt with in a far more primitive manner than today: NT4 Terminal Server Edition (TSE) had a special terminal server-only logon script mechanism. At logon, every command in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AppSetup registry value was executed. One of those commands was the execution of the batch file UsrLogon.cmd, the entry point of a set of pre-defined application compatibility scripts that could be customized by the administrator.
Among other things, these compatibility scripts tried to deal with the fact that old applications could not cope with paths in their stored configuration, they needed a single drive letter. The method of choice? “Subst” the real path to a user’s home directory with a drive letter. In essence, UsrLogon.cmd mapped a drive to a user’s home directory with the following command:
Subst %RootDrive% "%HomeDrive%%HomePath%"
The paragraphs above are written in past tense. But do not be fooled: the described functionality is still present in Windows Server 2003 and even 2008 terminal services, and it is still used as the case at hand demonstrates.
In his analysis of the problem the customer got to the point where UsrLogon.cmd calls SetPaths.cmd which in turn executes the following command:
"%systemroot%\Application Compatibility Scripts\ACRegL.exe" "%TEMP%\getpaths.cmd" COMMON_PATHS "HKLM\Software" "" GETPATHS
As the customer states in his forum post, ACRegL.exe fails whenever a logon is processed by Citrix User Profile Manager (logons on the same machine not processed by UPM are unaffected). This in turn causes %RootDrive% not to be mapped to %Homedrive%%HomePath% which ultimately makes a certain legacy application crash upon clicking on File -> Save. Not so good.
So what does ACRegL.exe even do? It reads some paths from the registry and writes the batch file GetPaths.cmd which then looks similar to the following:
SET COMMON_START_MENU=C:\Documents and Settings\All Users\Start Menu SET COMMON_STARTUP=C:\Documents and Settings\All Users\Start Menu\Programs\Startup SET COMMON_PROGRAMS=C:\Documents and Settings\All Users\Start Menu\Programs SET USER_START_MENU=C:\Documents and Settings\username\Start Menu SET USER_STARTUP=C:\Documents and Settings\username\Start Menu\Programs\Startup SET USER_PROGRAMS=C:\Documents and Settings\username\Start Menu\Programs SET MY_DOCUMENTS=My Documents SET TEMPLATES=Templates SET APP_DATA=Application Data
So where does it fail? As the faithful Process Monitor shows, the programmers of ACRegL.exe did a thorough job: they not only read some paths from the registry, but they verify if each path actually exists!
And with that we finally have solved the puzzle. In its default configuration, User Profile Manager excludes the start menu, i.e. it does not copy the start menu’s files and folders to the file server during logoff. During the next logon, assuming that the locally cached profile has been deleted, UPM copies everything back, except the start menu. When ACRegL.exe is called a little later by UsrLogon.cmd (still in the logon process), it does not find the start menu’s directories and fails.
In case you experience this problem, I recommend you do not exclude the start menu.
For the fun of it, here is a sequence of commands I used to verify my analysis. They were executed on a machine with UPM enabled for the current user, but without any exclusion lists.
H:\>"c:\WINDOWS\Application Compatibility Scripts\acregl.exe" "C:\DOCUME~1\test01\LOCALS~1\Temp\1\getpaths.cmd" COMMON_PATHS "HKLM\Software" "" GETPATHS H:\>echo %errorlevel% 0 H:\>rd /s /q "c:\Documents and Settings\test01\Start Menu\Programs\Startup" H:\>"c:\WINDOWS\Application Compatibility Scripts\acregl.exe" "C:\DOCUME~1\test01\LOCALS~1\Temp\1\getpaths.cmd" COMMON_PATHS "HKLM\Software" "" GETPATHS H:\>echo %errorlevel% 1
As you can see, at first ACRegL.exe works correctly. Only when the Startup folder is deleted, does it fail.