Tuesday, February 17, 2009

How to find Windows path

Once again Microsoft forgot something in the .NET Framework API. When it comes time to find the path of any special folder you can rely on “Environement.SpecialFolder” enumeration. Any? not quite. There is one missing: the Windows directory usually located at “C:\Windows”. See for yourself:

public enum SpecialFolder
{
    ApplicationData = 0x1a,
    CommonApplicationData = 0x23,
    CommonProgramFiles = 0x2b,
    Cookies = 0x21,
    Desktop = 0,
    DesktopDirectory = 0x10,
    Favorites = 6,
    History = 0x22,
    InternetCache = 0x20,
    LocalApplicationData = 0x1c,
    MyComputer = 0x11,
    MyDocuments = 5,
    MyMusic = 13,
    MyPictures = 0x27,
    Personal = 5,
    ProgramFiles = 0x26,
    Programs = 2,
    Recent = 8,
    SendTo = 9,
    StartMenu = 11,
    Startup = 7,
    System = 0x25,
    Templates = 0x15
}

Of course we can use environment variable “windir” to get it.

string windowsPath = Environment.GetEnvironmentVariable("windir");

But I don’t like to rely on hardcoded strings in my code. So looking with Reflector in the framework itself how Microsoft do that, I found:

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern string nativeGetWindowsDirectory();

static void Main(string[] args)
{
    string windowsPath = nativeGetWindowsDirectory();
	// ..
}

Hope this can help you avoid using stings in you code to get something as simple as a windows folder.

1 comment:

Anonymous said...

I think having a hardcoded string ("%SystemRoot%") is better than relying on an undocumented method.

Alternative, you could use the native documented WinSDK method SHGetSpecialFolderPath. For example:

public static String GetWindowsDirectory()
{
const uint CSIDL_WINDOWS = 0x24;
StringBuilder sb = new StringBuilder();
UnsafeNativeMethods.SHGetSpecialFolderPath(0, sb, CSIDL_WINDOWS, 0);
return sb.ToString();
}
//...
internal static class UnsafeNativeMethods
{
[DllImport("shell32.dll", SetLastError=true)]
public static extern int SHGetSpecialFolderPath(int hwndOwner, StringBuilder lpszPath, uint nFolder, int fCreate);
}