CSI_GetSpecialFolderToCMD Easily Retrieving Windows “Special” Folders in .CMD/.BAT and VBScripts. Print E-mail

In preparation for a Windows 7 migration the folder references in countless scripts used by administrators may need updating due to the changes in the standard Windows folder locations.  With the broad support for 64-bit Windows, there are also some path variances on the 64-bit platform.  If these scripts are updated with new literal location references they won’t work for both OSes during the migration and may not work on 64-bit Windows 7 or later on Windows 8.  Let’s look at how to modify your scripts so they work on all these variations simultaneously and become future proof.  This article also contains a very cool technique and sample code for being able to retrieve any special folder location in a shell script (.cmd or .bat) using a small VBScript.

This article is based on content we cover in our foundational course CSI-300 How Apps Work on Windows 7, which is the first two days of most of our tracks.

Hard-coding and Soft-Coding Disk Locations

Placing literal references such as “C:\Program Files\ABC\ABC.EXE” into your scripts is known as “Hard-coding” the reference.  The opposite approach of retrieving the location using local variables is known as “Soft-coding” the reference.  For example “%ProgramFiles%\ABC\ABC.EXE”  By looking up file system special folders, the code is able to account for many variations in folder structures across many versions and configurations of Windows.  Here are just a few of the issues that create variations in paths that are not handled by hard-coding:

  • Windows not installed on C: drive.
  • User profile location varies based on OS (e.g. XP and Win 7).
  • Custom user profile root folder created at install time.
  • Language localization in XP and before (on disk file locations were in local language)
  • Roaming profiles.
  • Redirected “My Documents”

Hard-coding and soft-coding can also be mixed.  For instance, rather than looking up the Documents folder for the current user, a script may retrieve the User’s profile using a variable and then tack on “My Documents”.  While this is better than no soft-coding it still creates an incorrect path in many situations.  For instance, when profiles have been redirected, this would result in a folder location that exists, but is not actually the user’s My Documents folder.  On Windows 7 this folder is called “Documents” (although Windows 7 also contains symbolic links for compatibility which allow the above reference to work – but ONLY IF the script is not listing the contents of the folder.)

Environment Variables Don’t Cut It

Environment variables have insufficient coverage of Windows special folders – which ends up encouraging partial soft-coding techniques. VBScript allows API access to retrieve most Windows folder locations programmatically, but the command shell does not have APIs to access special folders for which there is no environment variable.  This article contains a helper VBScript to allow special folder retrieval from shell scripts (.CMD/.BAT).  Since many people are familiar with environment variables, they use them VBScript as well, leading to some of the same partial soft-coding techniques as shell scripting does.

Windows 7 Folder Compatibility

Windows 7 uses symbolic file system links to create a level of compatibility between the folders locations that have changed since XP.  For instance “Documents and Settings” is now “Users”.  There is a hidden symbolic link at the root of your system drive that makes it look like “Documents and Settings” still exists to applications that try to use it.  However, there are some limitations to these compatibility links that can still trip up scripts (for instance, enumerating the symbolic link folders does not work).  To see the links, open a command prompt and change to C:\.  Use the command “dir /AL” to list links (even hidden one will display).  If you want to see all the compatibility links, add the subfolder recursion switch (“/s”) and pipe it to a file like this: “dir /AL /S > allsymlinks.txt”

Special Folder Retrieval in VBScript

The most comprehensive access to special folder values in VBScript is through the Namespace method of the Shell.Application object.  This method allows for use of the hexidecimal CSIDL constant values

However, you will quickly discover it’s not easy to map together the:

a) Folder you are looking for (e.g. “My Documents”)…

b) To the CSIDL constant name…

c) To the contant’s hex value…

d) To which folder that ACTUALLY is on the given versions of Windows you are trying to support with a single script.

The information is not simply in one place and it takes a lot of cobbling to get it correct.  There has to be an easier way!

There is!

Here is how to keep it simple:

a) Use CSI_ListAllSpecialFolders.vbs in the attachment to list all special folders on the OS(es) versions you are scripting for.

b) Code the hex value into CSI_GetSpecialFolderToCMDHyperSimple.CMD in the attachment.

A super simple way to configure a very simple script so that you can start creating scripts that work on with special folders on any version of Windows configured in a variety of ways!

A version of the script that uses folder constants is also in the zip file.

An alternate way to list special folders is to download SpecialFolderView from nirsoft.net and view the special folders on a sample systems (one for each OS type – e.g. XP and Windows 7) and find the hex value the correlates to the folder you are looking for.  SpecialFolderView shows the path on the current system, the CSIDL constant, CSIDL hex value and allows you to go to the folder by double clicking it – so you can be very certain you’ve found the appropriate hex value.

SpecialFolderView

Changelog:

5/23/2012 - Version 1.2 - added vbscript to list all special folders, added CMD version that exposes and uses constants to retrieve special folder

Attachments:
Download this file (CSI_GetSpecialFolderToCMD.zip)CSI_GetSpecialFolderToCMD.zip[Shell Script and VBS Helper Script to Retrieve Special Folders]3 Kb
 

Add comment


Security code
Refresh