Article: Windows Special Folders

Home Page


Consultancy

  • Service Vouchers
  • Escrow Service

Shop



Programming
  • Articles
  • Tools
  • Links

Search

 

Contact

 

PHPinfo


$_SERVER







How to use "Special Folders" for accessing files the user may not be aware of.

category 'KB', language C#, created 09-May-2011, version V1.0, by Luc Pattyn


License: The author hereby grants you a worldwide, non-exclusive license to use and redistribute the files and the source code in the article in any way you see fit, provided you keep the copyright notice in place; when code modifications are applied, the notice must reflect that. The author retains copyright to the article, you may not republish or otherwise make available the article, in whole or in part, without the prior written consent of the author.

Disclaimer: This work is provided as is, without any express or implied warranties or conditions or guarantees. You, the user, assume all risk in its use. In no event will the author be liable to you on any legal theory for any special, incidental, consequential, punitive or exemplary damages arising out of this license or the use of the work or otherwise.


Most Windows applications deal with documents, which are files the user is aware of, and in charge of; he can choose their name and their location in the file system. Most applications however also need to read from, and sometimes write to, some special files the user is not always aware of, e.g. when dealing with application settings, logging, or what have you. The problem then is where to store such files.

Windows has a concept of "Special Folders". They are suppported through Win32 API calls such as SHGetSpecialFolderPath (in shell32.dll) and through the Environment.GetSpecialFolder() method in the .NET FrameWork.

An example

This example writes some log messages to a log file in a way that should work fine on all Windows systems; it uses a special folder "ApplicationData" that is specific to the current user, and gives him write access.

using System;
using System.Diagnostics;	// Process
using System.IO;		// Path

namespace SpecFolders1 {
    public class Example1 {
	string COMPANY_NAME = "myCompany";
	string APP_NAME	= "myApp";
	string logFile;

	public void Run() {
	    logFile = Path.Combine(getAppFolderName(), "logfile.txt");
	    log("start logging to file "+logFile);
	    log("half-way");
	    log("done");
	    Process.Start(logFile); // open file in Notepad
	}

	// construct the folder	name, and make sure the	directory exists
	private	string getAppFolderName() {
	    string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
	    folder = Path.Combine(folder, COMPANY_NAME,	APP_NAME);
	    Directory.CreateDirectory(folder);	// make	sure it	exists
	    return folder;
	}

	// log one line	of text
	private	void log(string	s) {
	    s =	DateTime.Now.ToString("HH:mm:ss.fff ") + s;	// add a time stamp
	    Console.WriteLine(s);
	    File.AppendAllText(logFile,	s + Environment.NewLine);
	}
    }
}
The log file looks like so:
22:33:10.619 start logging to file C:\Users\MyName\AppData\Roaming\myCompany\myApp\logfile.txt
22:33:10.962 half-way
22:33:10.964 done

Notes:

  1. Within most special folders, one should create a little folder hierarchy to make sure different applications don't get confused about all the available files. The normal approach is having a company level, and an application level, as has been shown in the example; it is similar to what is done most often in the registry.
  2. Once the folder path has been chosen, one should make sure all the folders exist; there is no need to test for that, a simple call to Directory.CreateDirectory() will take care of eveything.
  3. On a standard Vista system the "AppData" folder for user "MyName" is called C:\Users\MyName\AppData\Roaming\ so the example generates file C:\Users\MyName\AppData\Roaming\myCompany\myApp\logfile.txt

Always use the official way to get those folders

While one could come up with alternate schemes, that would be hard and error-prone; it is strongly recommended to always use the official way, and call the appropriate classes and methods. Here are a few reasons why:

  1. Putting data files in the same folder as the application files (the EXE) themselves is not a good idea; oftentimes the application will be installed in the Program Files folder, and that folder may or may not be write-protected at the administrator's discretion.
  2. Some of the special folders have changed names over time. For example, up to Windows XP there used to be a Documents and Settings folder holding a personal folder for every user; since Vista that folder has been renamed to Users.
  3. Some special folders can be relocated by the system administrator; for example, he might choose to put the user "Documents" on a different partition.

Which folder to use

The number of available special folders depends on two things:

  1. the actual number of known special folders depends on the version of Windows that is being used; this MSDN page lists 57 of them, and comments on their availability
  2. as .NET identifies those special folders through the ever growing Environment.SpecialFolder enum, the availability of special folders also depends on the .NET version being used.

Fortunately most situations can be dealt with using only a few of the special folders, and these have been available for a long time now. Here is a attempt to classify all the special folders:

[3A] CommonOemLinks=
[39] LocalizedResources=
[11] MyComputer=

[26] ProgramFiles=		C:\Program Files
[2A] ProgramFilesX86=		C:\Program Files
[2B] CommonProgramFiles=	C:\Program Files\Common Files
[2C] CommonProgramFilesX86=	C:\Program Files\Common Files

[24] Windows=			C:\Windows
[14] Fonts=			C:\Windows\Fonts
[38] Resources=			C:\Windows\resources
[25] System=			C:\Windows\system32
[29] SystemX86=			C:\Windows\system32

[2F] CommonAdminTools=		C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools
[23] CommonApplicationData=	C:\ProgramData
[17] CommonPrograms=		C:\ProgramData\Microsoft\Windows\Start Menu\Programs
[16] CommonStartMenu=		C:\ProgramData\Microsoft\Windows\Start Menu
[18] CommonStartup=		C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
[2D] CommonTemplates=		C:\ProgramData\Microsoft\Windows\Templates

[28] UserProfile=		C:\Users\MyName
[15] Templates=			C:\Users\MyName\AppData\Roaming\Microsoft\Windows\Templates
[30] AdminTools=		C:\Users\MyName\AppData\Roaming\Microsoft\Windows\Start	Menu\Programs\Administrative Tools
[1A] ApplicationData=		C:\Users\MyName\AppData\Roaming
[3B] CDBurning=			C:\Users\MyName\AppData\Local\Microsoft\Windows\Burn\Burn
[21] Cookies=			C:\Users\MyName\AppData\Roaming\Microsoft\Windows\Cookies
[00] Desktop=			C:\Users\MyName\Desktop
[10] DesktopDirectory=		C:\Users\MyName\Desktop
[06] Favorites=			C:\Users\MyName\Favorites
[22] History=			C:\Users\MyName\AppData\Local\Microsoft\Windows\History
[20] InternetCache=		C:\Users\MyName\AppData\Local\Microsoft\Windows\Temporary Internet Files
[1C] LocalApplicationData=	C:\Users\MyName\AppData\Local
[0D] MyMusic=			C:\Users\MyName\Music
[27] MyPictures=		C:\Users\MyName\Pictures
[0E] MyVideos=			C:\Users\MyName\Videos
[13] NetworkShortcuts=		C:\Users\MyName\AppData\Roaming\Microsoft\Windows\Network Shortcuts
[1B] PrinterShortcuts=		C:\Users\MyName\AppData\Roaming\Microsoft\Windows\Printer Shortcuts
[02] Programs=			C:\Users\MyName\AppData\Roaming\Microsoft\Windows\Start	Menu\Programs
[08] Recent=			C:\Users\MyName\AppData\Roaming\Microsoft\Windows\Recent
[09] SendTo=			C:\Users\MyName\AppData\Roaming\Microsoft\Windows\SendTo
[0B] StartMenu=			C:\Users\MyName\AppData\Roaming\Microsoft\Windows\Start	Menu
[07] Startup=			C:\Users\MyName\AppData\Roaming\Microsoft\Windows\Start	Menu\Programs\Startup
[05] MyDocuments=		H:\LP_Documents
[05] Personal=			H:\LP_Documents

[19] CommonDesktopDirectory=	C:\Users\Public\Desktop
[2E] CommonDocuments=		C:\Users\Public\Documents
[35] CommonMusic=		C:\Users\Public\Music
[36] CommonPictures=		C:\Users\Public\Pictures
[37] CommonVideos=		C:\Users\Public\Videos

Conclusion

It works fine when used as intended

History

  • Version 1.0 (09-May-2011): Original version


Perceler

Copyright © 2012, Luc Pattyn

Last Modified 04-May-2025