Environment.SpecialFolder and Environment.GetFolderPath() in Mono and .Net

Section: Programming

While investigating what users wanted as a default save/export directory I investigated what common folders were defined in Mono and .Net that allowed developers to save things in user directories. Environment.SpecialFolder.ApplicationData provides a useful place for stashing saved preferences and caches etc, but is generally a hidden folder and so isn't so useful for saving the user's exported data. As it turns out there are a number of "special folders" whose defaults exist in Linux and Windows that could be used for sensible (if not ideal) values

Investigative code

The following code snippet outputs all of the special folder values for a system:

// This code snippet is licensed and distributed, without warranty, under the GNU Affero GPL license (http://www.gnu.org/licenses/agpl-3.0.html), either version 3 of the License or (at your option) any later version..
using System;

namespace IBBoard.Example.SpecialFolders
	class MainClass
		public static void Main (string[] args)
			foreach(Environment.SpecialFolder folder in Enum.GetValues(typeof(Environment.SpecialFolder)))
				Console.WriteLine(String.Format("{0}\t\t\t{1}", folder.ToString(), Environment.GetFolderPath(folder)));

On an openSUSE 11.2 (and presumably most Linux systems) this outputs:

Desktop			/home/ibboard/Desktop
Personal			/home/ibboard
Personal			/home/ibboard
MyMusic			/home/ibboard/Music
DesktopDirectory			/home/ibboard/Desktop
ApplicationData			/home/ibboard/.config
LocalApplicationData			/home/ibboard/.local/share
CommonApplicationData			/usr/share
MyPictures			/home/ibboard

On a standard Windows XP it outputs:

Desktop                 C:\Documents and Settings\ibboard\Desktop
Programs                        C:\Documents and Settings\ibboard\Start Menu\Programs
Personal                        C:\Documents and Settings\ibboard\My Documents
Personal                        C:\Documents and Settings\ibboard\My Documents
Favorites                       C:\Documents and Settings\ibboard\Favorites
Startup                 C:\Documents and Settings\ibboard\Start Menu\Programs\Startup
Recent                  C:\Documents and Settings\ibboard\Recent
SendTo                  C:\Documents and Settings\ibboard\SendTo
StartMenu                       C:\Documents and Settings\ibboard\Start Menu
MyMusic                 C:\Documents and Settings\ibboard\My Documents\My Music
DesktopDirectory                        C:\Documents and Settings\ibboard\Desktop
Templates                       C:\Documents and Settings\ibboard\Templates
ApplicationData                 C:\Documents and Settings\ibboard\Application Data
LocalApplicationData                    C:\Documents and Settings\ibboard\LocalSettings\Application Data
InternetCache                   C:\Documents and Settings\ibboard\Local Settings\Temporary Internet Files
Cookies                 C:\Documents and Settings\ibboard\Cookies
History                 C:\Documents and Settings\ibboard\Local Settings\History
CommonApplicationData                   C:\Documents and Settings\All Users\Application Data
System                  C:\WINDOWS\system32
ProgramFiles                    C:\Program Files
MyPictures                      C:\Documents and Settings\ibboard\My Documents\My Pictures
CommonProgramFiles                      C:\Program Files\Common Files

I don't know why "Personal" is duplicated in the list, as they both seem to be the same enum value, but the code just loops over the values that are given to it and it makes a consistent appearance as a duplicate!

The usable values

Based on the output above, the following Environment.SpecialFolder enum values are usable with the Environment.GetFolderPath() method and give sensible values for .Net apps on Windows and Mono apps on Linux:

  • Desktop
  • Personal
  • MyMusic
  • DesktopDirectory
  • ApplicationData
  • LocalApplicationData
  • CommonApplicationData
  • MyPictures

The best place to default to saving files in is probably the Environment.SpecialFolder.Personal folder, as it equates to My Documents in Windows (a hellish mess of a folder that generally contains everything, not just documents) and the user's home directory in Linux (which really is their home directory that contains everything). Some of the other options may be useful for Windows-only applications, but if you're writing in a .Net language then why make what could be easy cross-platform compatibility hard by using unsupported or unspecified folders?