2012-11-24

Application Data Directories on Windows/Mac

I'm writing an application that will support both Windows and Mac, and it's arrived at the point in its development where it needs its first data file. What directory should it be stored it? For the purposes of this post, let's assume that the files are not something that the user is supposed to generally interact with directly (as in that case, it might be more appropriate to put it in a Documents folder of some sort).

It looks like in modern Windows (as of this writing, Windows 8/Server 2008 R2), there are several options recommended by Microsoft for storing application data, each with a slightly different purpose. Their locations can be looked up via SHGetKnownFolderPath if you pass in the appropriate KNOWNFOLDERID. Many of these folders are hidden (so tweak your display settings if needed to see them).

  • RoamingAppData: User-specific application data this is intended to "roam" (synchronize with a central user profile server).
    • This can be accessed vis the %APPDATA% environment variable.
    • In Windows Vista and later, this defaults to C:\Users\USERNAME\AppData\Roaming.
    • In Windows XP and earlier, this defaults to C:\Documents and Settings\USERNAME\Local Settings\Application Data (and wasn't separate from LocalAppData).
  • LocalAppData: User-specific application data that is not intended to "roam" due to either large size or being machine-specific.
    • This can be accessed via the %LOCALAPPDATA% environment variable in Windows Vista and later. In Windows XP and earlier, you can fall back to %APPDATA%.
    • In Windows Vista and later, this defaults to C:\Users\USERNAME\AppData\Local.
    • In Windows XP and earlier, this defaults to C:\Documents and Settings\USERNAME\Local Settings\Application Data (and wasn't separate from RoamingAppData).
  • LocalAppDataLow: Similar to LocalAppData but for "low integrity data", meaning that the originating user cannot be trusted. It's pretty rare to have reason to use this one.
    • In Windows Vista and later, this defaults to C:\Users\USERNAME\AppData\LocalLow.
  • ProgramData: Non-user-specific application data.
    • This can be accessed via the %ProgramData% environment variable in Windows Vista and later. In Windows XP and earlier, you can fall back to %ALLUSERSPROFILE%\Application Data.
    • In Windows Vista and later, this defaults to C:\ProgramData.
    • In Windows XP and earlier, this defalts to C:\Documents and Settings\All Users\Application Data.

From this, we now know what questions to ask. Are the files user-specific? If not, use ProgramData. If so, should they roam? If so, use RoamingAppData, otherwise use LocalAppData. If you're only targetting Windows Vista/Server 2008 and later, you can use either SHGetKnownFolderPath or an environment variable to get the right path. If you want to support Windows XP/Server 2003, it gets a bit more complicated. You can use environment variables, but for some of them, you need to add fallback logic for the appropriate XP environment variable. If you're using the Windows API, SHGetFolderPath can be used in Windows 2000 or later, with the CSIDL equivalent of the FOLDERID constants. In Java, probably the easiest way to do so is to use JNA's wrapper of this function, like this:

Shell32Util.getFolderPath(ShlObj.CSIDL_LOCAL_APPDATA)

You should use either a CompanyName\ApplicationName or ApplicationName subdirectory in these known folders rather than writing files in them directly. Note that the ProgramData folder is intended to be writable only by admin users. When User Account Control (UAC) is in play, that means that even admin users can't write to it unless they're running in a permission-elevated context. If you want your program to be able to write to an application-specific ProgramData subfolder without requiring elevation, have your installer create the directory and set an appropriate ACL to grant the needed permissions.

Now that we've got Windows squared away, what about Mac OS X? The Library folder in various domains is used for application data. More specifically:

  • ~/Library (default of /Users/USERID/Library): User-specific application data.
  • /Library: Non-user-specific application data.

The Mac OS X documentation specifies using particular subdirectories within a Library directory. For most purposes, you'll want to use the Application Support directory, which is to be used for "all app data files except those associated with the user's documents".

You should use a subdirectory of Application Support rather than writing files in it directly. The documentation says to use your bundle identifier (com.example.MyApp), but it looks to me like it is more common to use the application name instead. In Lion, the default permissions on /Library/Application Support changed such that users can't write to this directory without elevated permissions. If you want your program to be able to write to a directory within that area without requiring elevation, have your installer create the directory and set appropriate permissions.

The API provided locate known directories appears to be NSSearchPathForDirectoriesInDomains (which can be called via Rococoa). That would allow handling cases such as searching for a file across multiple domains. In many cases, it may be sufficient to simply look in a single directory, however.

Related articles: