Wednesday, April 14, 2010

Taming All Users Desktop and Start Menu Environment Variables in Windows 7 and XP

Some Background


This week I installed Windows 7. I enjoy many of the new features but have also come across several annoyances. I expected to have a few issues but those relating to batch scripting and the location of profile information are particularly perplexing. There may be some rationale behind moving the data but I haven't been able to find an official Microsoft explanation. At my job we manage thousands of workstations so we've got a heavily scripted deployment environment. It is extremely efficient except during transitional periods when we are between operating systems. Currently, we are testing a lab of Windows 7 machines but will still plan on supporting well over 2000 Windows XP machines for several more years. My goal is to make the transition to Windows 7 as painless and quick as possible. Before I can do that however I must get our batch scripts to be cross-OS between Windows 7 and Windows XP. I've left out Vista because we never deployed a single Vista machine (thank goodness). Enough babble, onward!

The Guts of the Problem


When writing batch scripts in Windows XP, you can access the All Users Desktop and Start Menu paths using these enironment variables:

%ALLUSERSPROFILE%\Desktop
%ALLUSERSPROFILE%\Start Menu


These really made it quite easy to...
  • script a file copy
  • pass these paths as parameters to other scripts or programs
  • or even to open to these locations in windows explorer
In Windows 7, for unknown reasons, the environment variables have been modified and the All Users Desktop and Start Menu paths have been moved to completely separate folders. So you'll need to use these variables instead:

%PUBLIC%\Desktop
%PROGRAMDATA%\Microsoft\Windows\Start Menu\


Technically you could use the Windows XP environment variables, but they don't work as expected in all situations. Here is a simple demonstration. Open an elevated command prompt and type the following 3 commands and hit enter after each line.

cd %ALLUSERSPROFILE%\Desktop
mkdir test
dir


Now, look on your Desktop. The directory "test" was successfully created. Great! That part worked. Now, head back to the command prompt for the bad news. After you typed the dir command we would expect to see a directory listing that lists the directory "test". Instead we are greeted with an empty, unhelpful directory listing that states "File Not Found". Well we just created a directory so we know this just isn't true. Something has gone horribly wrong. If you want another example of why this is a problem simply type %ALLUSERSPROFILE%\Desktop into Windows Explorer. You'll get an access denied message. Fail.

So we are in a bit of a bind here. We don't want to write a bunch of IF/ELSE statements in our scripts but since the paths returned by environment variables are flawed we really don't have any other choice. So how can we do this in as few lines as possible? Continue below for a 1 line solution that requires some editing of your Windows XP only scripts.

A Crude but Acceptable Solution


Place the following one line of code (there should not be a line break) at the top of your batch scripts then use %AUDESKTOP% or %AUSTARTMENU% to refer to the All Users Desktop and Start Menu respectively.

IF DEFINED PUBLIC (SET AUDESKTOP=%PUBLIC%\Desktop) & (SET AUSTARTMENU=%PROGRAMDATA%\Microsoft\Windows\Start Menu) ELSE (SET AUDESKTOP=%ALLUSERSPROFILE%\Desktop) & (SET AUSTARTMENU=%ALLUSERSPROFILE%\Start Menu)

Here is a little demo script that you can use to make sure the script is working correctly in your environment:

IF DEFINED PUBLIC (SET AUDESKTOP=%PUBLIC%\Desktop) & (SET AUSTARTMENU=%PROGRAMDATA%\Microsoft\Windows\Start Menu) ELSE (SET AUDESKTOP=%ALLUSERSPROFILE%\Desktop) & (SET AUSTARTMENU=%ALLUSERSPROFILE%\Start Menu)
ECHO All Users Desktop is at path: %AUDESKTOP%
ECHO All USers Startup is at path: %AUSTARTMENU%
pause


There may be other differences in environment variable names between Windows 7 and Windows XP and this script could certainly handle those if discovered. Please post them in the comments for the rest of us.

How to Actually Implement It?


Ok let's assume you have a simple batch script such as the one below that currently only works in Windows XP but that you'd like to get working in Windows 7 too. All it does is open two Windows Explorer windows (one to the all users desktop and one to the all users start menu) but is giving you two access denied errors in Windows 7:

%SystemRoot%\Explorer.exe /n, "%ALLUSERSPROFILE%\Desktop%"
%SystemRoot%\Explorer.exe /n, "%ALLUSERSPROFILE%\Start Menu"


Your modified, cross-OS script should read like this and will work properly in both Windows 7 and Windows XP:

IF DEFINED PUBLIC (SET AUDESKTOP=%PUBLIC%\Desktop) & (SET AUSTARTMENU=%PROGRAMDATA%\Microsoft\Windows\Start Menu) ELSE (SET AUDESKTOP=%ALLUSERSPROFILE%\Desktop) & (SET AUSTARTMENU=%ALLUSERSPROFILE%\Start Menu)
%SystemRoot%\Explorer.exe /n, "%AUDESKTOP%"
%SystemRoot%\Explorer.exe /n, "%AUSTARTMENU%"


Voila! You have a cross browser script. Now, I admit it is a pain to go through and Find/Replace all the instances of the old style of scripting but if you have a large enough support environment it will be worth your time since you won't have to have two versions of the same script and only has to be done this one time.

One Final Caveat


Remember, when you run batch scripts that access either of these folders you're going to need elevated (administrator) permissions. This means you need to right click on the script and choose "Run as administrator".

If anyone finds a better way to implement this or knows of a hidden environment variable that I am missing, please let me know!

11 comments:

  1. This is exactly what I needed. Good job! I just wish someone would come right out and say that the location C:\ProgramData\Desktop was a dead end in Windows 7, making your script do nothing with no errors.

    ReplyDelete
    Replies
    1. Agreed. Not sure why it was done this way. I like the XP way better but do prefer Users to "Documents and Settings". MS just can't seem to get it quite right!

      Delete
  2. Great bit of script! This is exactly what I was looking for when running a simple install script on multiple Windows XP & 7. Thanks.

    ReplyDelete
    Replies
    1. No problem. Glad it could be of use. Please let me know if you get a chance to use it in Windows 8. I've been wondering if it works in that environment.

      Delete
  3. thanks, not exactly what i need, but enought to find de way!

    ReplyDelete
  4. I am testing on Windows 8 and see that the shortcuts created by my application does not work until the machine is rebooted after I install the application ? Any ideas why ?

    ReplyDelete
    Replies
    1. RMK. I don't have a Windows 8 box yet for testing. Can you post a code snippet of how you're creating the shortcuts? I can take a look.

      Delete
    2. Thanks Jim.
      We use Basic MSI project and use CreateShortCut provided by Installshield to create the shortcut. Let me know if you need further details.

      Delete
    3. RMK, I'm afraid I haven't used this in the context of MSI Basic project in InstallShield. I generally use this in fairly batch scripts. I was able to find a bit of information here that suggests at least advertised shortcuts have a few issue in Windows 8. Perhaps Christopher would be able to confirm for you: http://blog.iswix.com/2012/11/windows-8-changes-setup-developers-need.html

      Are you using the current version of InstallShield or an older version? It sounds like Win 8 introduces some new variables into the mix in terms of installations. For example, how do old installers register a tile? How do they overcome the changes to UAC. It seems that InstallShield may be able to answer those kinds of question. As soon as I get my hands on a Windows 8 box I will test this script again and report back to see if it returns the proper results.

      If all else fails. Can you let me know what the variables %AUDESKTOP% and %AUSTARTMENU% are set to when you use the script above? You should just be able to echo them out using a batch script.

      Thanks!

      Jim

      Delete