Where Should I Write Program Data Instead of Program Files?
Published Aug 14 2018 04:00 PM 1,874 Views
Microsoft
First posted to MSDN on Feb, 05 2008

When I'm working to resolve compatibility issues, there are always multiple options to mitigate. The solution we prefer to use is to update the code.

A common application code update is this: "my application used to write files to program files. It felt like as good a place to put it as any other. It had my application's name on it already, and because my users were admins, it worked fine. But now I see that this may not be as great a place to stick things as I once thought, because with UAC even Administrators run with standard user-like privileges most of the time. So, where should I put my files instead?"

The answer, as it turns out, is: it depends.

Let's look at the options, and when you might want to choose each.

First, you'll want to use the SHGetKnownFolderPath API function to pull the function if you are using native code. If you are using managed code, System.Environment.GetFolderPath will do the trick for you.

FOLDERID_ProgramData / System.Environment.SpecialFolder.CommonApplicationData
The user would never want to browse here in Explorer, and settings changed here should affect every user on the machine. The default location is %systemdrive%ProgramData, which is a hidden folder, on an installation of Windows Vista. You'll want to create your directory and set the ACLs you need at install time.

FOLDERID_Public / FOLDERID_PublicDocuments / System.Environment.GetEnvironmentVariable("public")
The user would want to browse here in Explorer and double click to open the file. The default location is %public%, which has explicit links throughout Explorer, on an installation of Windows Vista. You'll want to create your directory and set the ACLs you need at install time.

FOLDERID_RoamingAppData / System.Environment.SpecialFolder.ApplicationData
The user would never want to browse here in Explorer, and settings changed here should roam with the user. The default location is %appdata%, which is a hidden folder, on an installation of Windows Vista.

FOLDERID_LocalAppData / System.Environment.SpecialFolder.LocalApplicationData
The user would never want to browse here in Explorer, and settings changed here should stay local to the computer. The default location is %localappdata%, which is a hidden folder, on an installation of Windows Vista.

FOLDERID_Documents / System.Environment.SpecialFolder.MyDocuments
The user would want to browse here in Explorer and double click to open the file. The default location is %userprofile%documents, which has explicit links throughout Explorer, on an installation of Windows Vista.

Now, you'll note that FOLDERID_Public is kind of the oddball here. System.Environment.GetFolderPath just calls SHGetFolderPath, which takes CSIDLs. There is no analogue for %public% here. However, we could have gone after CSIDL_COMMON_DOCUMENTS (FOLDERID_PublicDocuments) and dropped things there, but even though we just need to pass 0x2e (46) as the int argument, we don't offer that. Because we have this subset going, I'd probably start thinking about using p/invoke if I needed to support public documents ( http://www.pinvoke.net/default.aspx/shell32.SHGetKnownFolderPath ).

If you're using Visual Basic, you can also use My.Computer.FileSystem.SpecialDirectories, but it also doesn't seem to get any public documents love...

Version history
Last update:
‎Nov 13 2018 08:08 AM
Updated by: