tags:

views:

569

answers:

8

Our win32 applications (written in C++) have been around for over 10 years, and haven't been updated to follow "good practices" in terms of where they keep files. The application defaults to installing in the "C:\AppName" folder, and keeps application-generated files, configuration files, downloaded files, and saved user documents in subfolders of that folder.

Presumably, it's "best practices" to default to installing under "c:\Program Files\AppName" nowadays. But if we do that, where should we keep the rest of our files? Starting from Vista, writing to the program files folder is problematic, and there seem to be a million other places that you can put different files, and I'm confused.

Is there a reference somewhere for what goes where?


Edit: To expand on questions people have asked so far:


I'm familiar with the SHGetFolderPath function, but there are lots and lots of options that you can get from it, and I can't find a resource that says "Here is exactly what each of these options is used for, and when you might want to use it".

Up until now, we've done the "All files, including saved user files, under one folder" thing, and it's worked fine - but not when people want to install the app under the Program Files folder. For some reason, the virtualization monkeying around that Vista does isn't working for our application; if we're going to be making changes anyway, we might as well make an effort to do things the "right" way, since we don't want to have to change it again in 12 months time.


Further question:


We include some "sample" documents with our app, which we update every now and again. Is it appropriate to install them into My Documents, if we'll be overwriting them every few months? Or is My Documents assumed to be totally safe for users to mess around in?

If we can't install them to My Documents, where should we put them so that users can see them easily?

+4  A: 

Use the Windows SHGetFolderPath() function to get the correct directories.

Edit: To reply to your other question, added in the edit: Where to put the sample files of your application does very much depend on whether your application is installed for a single user or for all users, and whether the person installing the application can be assumed to be the one who uses it.

If your program is to be used by multiple users on a system, copying stuff into "My Documents" is not going to work - the files would be accessible only for the user installing the application. Worse, if the only user of your application needed to install as Administrator, then [s]he will not have access to the files either. So unless you are fairly certain that there is only one user for your application, and they have sufficient permissions to install the application using their own account, don't use "My Documents".

IMO you should install sample files into the directory identified by CSIDL_COMMON_APPDATA. This will give you exactly one copy for all users, and since you want every user to see the original, unaltered sample files all users should consider them read-only. In fact, your setup program should probably make them read-only. Opening one of the samples will work for all users, but as soon as they try to save their modifications the application should detect that the file is read-only, and open the "Save As" dialog, pointing to "My Documents" or suitable directory inside. That will also keep all user modifications when the installer updates the sample files later on.

It is of course somewhat more difficult for the users to find the sample files. You could add a link to the samples folder to the start menu group of your application, so that access to the files is fast, and of course you should properly document everything.

mghie
Nice going with the downvote. Care to explain the reasoning, if there is any?
mghie
Unrelated to any downvoting, "Note As of Windows Vista, this function is merely a wrapper for SHGetKnownFolderPath. The CSIDL value is translated to its associated KNOWNFOLDERID and then SHGetKnownFolderPath is called. New applications should use the known folder system..."
JMD
Good point, have amended my answer.
Paul Dixon
OK. If all your users are on Vista, poor things...
mghie
+1 for read-only files in CSIDL_COMMON_APPDATA.
MSalters
+12  A: 

Presumably, it's "best practices" to default to installing under "c:\Program Files\AppName"

Close, but not quite. Users can configure the name of the Program Files folder and may not even have a C: drive. Instead, install to the %ProgramFiles%\AppName environment variable folder. Note that you should assume you only have read access to this folder after the installation has finished.

For program data files where you might need write access, use %AppData%\AppName.

Finally, are you sure yours is the only app with that name? If you're not 100% certain of that, you might want to include your company name in there as well.

The mechanisms you use to retrieve those variables will vary depending on your programming platform. It normally comes down to the SHGetFolderPath() method in the end, but different platforms like Java or .Net may provide simpler abstractions as well.

Joel Coehoorn
I was halfway through saying pretty much the same thing when I loaded this answer. +1
Randolpho
Have I seen you at devshed before, randolpho?
Joel Coehoorn
Probably, I used to frequent there back in the day. I've got stack overflow under my skin these days, though. :)
Randolpho
A: 

We have a similar app created ~10 years ago using MFC. The easiest thing to do was create a folder right off of C:\ (e.g. C:\OurApp). No install files, no special permissions, no registry changes, etc. Clients (and particularly their sys admins) LOVE it.

One other consideration - are you planning to all of a sudden change the installation folder for existing clients (assuming this is installed in many locations)? If something isn't broke, why fix it?

Jess
I think that's exactly the pattern he's trying to correct.
JMD
SysAdmins these days aren't so thrilled with that any more. Since users won't have rights there by default deployment is a hassle.
Joel Coehoorn
With no install files, how do users uninstall it? Have you ever tested installing and running your with an XP limited user or a Vista standard user?
Jim In Texas
To uninstall, our users just delete the folder. We've never had any problems with desktop permissions in XP or Vista environments. Now we only have 400 or so client desktops running our software, but it has worked great.
Jess
"XCOPY deployment" isn't actually /that/ bad. Sure, users can accidentily delete the entire application, or drag it somewhere else, but if your users are IT professionals that's unlikely. Joe Sixpack will, however,
MSalters
A: 

There is a directory structure under c:\users for user oriented data.

There is documentation for porting apps from older windows OSs to Vista.

Check out http://www.innovateon.com and follow the links to Vista. There is documentation regarding certification that has the details on topics like this.

Greg Oliver
-1, it's not defined to be C:\ . In my multiboot installs, it was sometimes assigned as J:\ , for example. Fun times.
Adriano Varoli Piazza
On 99% of computers, it's c:\. The main point is this: documentation exists that tells folks how to port to Vista, where to put things, etc. Here's a "closer" link:http://www.innovateon.com/pageLayout.aspx?pageID=VistaCertBuildTake a look at the requirements doc.
Greg Oliver
A: 

Sorry I don't know the correct answer, but...

Do you have a business case for wanting to do that? Are your customers complaining that files aren't stored where they expect? Are your applications crippled in some way because you store files in non-standard locations? If not, I don't see a reason for spending time and budget to redo your file storage strategy just to meet "best" practice. If your programs just work, then IMHO you should leave them alone and spend money and time on things that matter.

Kristo
You run a very real risk that the program does not run under non-administrator accounts on Vista and later versions of Windows. That may be the death-sentence for the app in corporate environments.
mghie
Ah, good to know. Thanks. So that means his apps might in fact be crippled in some way, and he does in fact have a valid business case.
Kristo
+8  A: 

Some guidelines are in this Knowledge Base article: How to write a Windows XP Application that stores user and application data in the correct location by using Visual C++. Also, if you search MSDN for Windows Logo Program you will find documentation regarding what an app needs to do to be truly compliant.

SHGetKnownFolderPath can get you the directories you need. If backwards compatibility with XP and earlier is required, use the deprecated SHGetFolderPath

Having said that, if you app came with documentation that said "everything used by this app is in this directory" I would love it ;)

Paul Dixon
FYI, I left a comment with mghie's answer that MSFT says SHGetFolderPath is deprecated in favour of SHGetKnownFolderPath.
JMD
A menu command that says "Show ancillary file folder" that opens Explorer to the proper folder would be awesome too.
Mark Ransom
A: 

There are plenty of environment variables like: %USERPROFILE%, %HOMEPATH%, %APPDATA% all of these points to some user-specific directories, where you can put your user-specific files.

For system-wide storage you can use %ALLUSERSPROFILE%, that is the place where you should put your read/write datafiles that are not specific to any user.

Jiri
+2  A: 

For your application binaries, you can assume that you may write to the PROGRAM FILES directory (use the %ProgramFiles% environment variable to support installations other than the default English version - e.g. in german Installations this will be c:\Programme by default). Wikipedia lists the most common variables. Another option are the SHGetFolderPath or newer SHGetKnownFolderPath functions.

For User data, you should assume that the application is running with limited access rights and may only write to the user's home directory. Same applies for registry entries. This path should probably be configurable b the user, as the home directory may actually be a network server and a user might have a second disk attached for data storage. For information on the current (Vista) filesystem guidelines see this article.

Regarding plugins, this might be more complicated. The best practice seams to be offering the option to install for the current user only, and placing the plugin in the user directory, or install for all users and place the files into your program files directory (but remember to check for write permission and request elavated access if needed).

VolkA
Useful white paper link - thanks!
Colen