Where should my win32 program keep its files? - c++

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?

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 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() Win32 method in the end, but different platforms like Java or .Net may provide simpler abstractions as well.

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 ;)

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.

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).

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.

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.

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.

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?

Related

Create hidden configuration file for C++ Linux applications

I'm creating a C++ linux application that needs some initial parameters of configuration to work correctly, these externals configurations is needed to avoid multiple compilations for parameters changes, and this configurations needs to be unknow by the end users. I was thinking an way do make an hidden configuration file that is consumed at the first execution, and always is researched at execution to verify possibles changes. Some suggestion to do this?
It is unlikely that you can hide the configuration file so that people do not know its existence: most Linux users would want to know which files you are installing in which location, and there are many ways to help them in discovering that, even if you try to do it without telling them (the simplest way that comes to my mind, they may do a file system snapshot and compare it before and after running the install program)
If your goal is to prevent people from changing the configuration without your permission (i.e., without paying for a license upgrade), you may do it by requiring the configuration to be signed from your company, storing the verification key inside the executable.
If you want to prevent the configuration from being read you don't have that much luck: there is not much that can stop a motivated attacker from reading the content of that file, since your application must be able to do it as well.

Is it possible to access files on iOS with the various compiler applications?

I recently downloaded the "CppCode" app for my iPhone and I was just wondering if it was at all possible to access files, change settings, delete things, make calls, etc.
Let's say I wanted to send a text to a friend - could this be possible within the C++ compiler on the iPhone?
This isn't really a question for stackoverflow, but the answer is no. Your phone, by default, protects its files from apps. Each app exists in its own "sandbox", and is not allowed to leave it under any circumstances. This is what jailbreaking does, it gives you root access to the rest of your phone's internal directories. Even then, I don't think it would be possible. If you really want to do stuff with that, you're better off making an app. I wouldn't try to program stuff from inside some compiler program on-board the phone..

c++ solution to locking a directory - linux

A simple question. Is it possible to lock a directory under linux ? Actually what I need is that only one application (which I wrote) has an access to a specified directory which is created by this application. So basically it is a cache directory for that app and so-far users have been messing with it. so i wish to prevent this in future.
Is it possible to do this?? and how (language: c++)?
Not possible in standard C++ at all.
Under linux, use setuid permissions on the executable, so it runs in context of its owner. Then you can lock down access permissions for the directory, so it is only accessible to the owner of the executable.
Of course, this doesn't stop users using your program from messing with your cache. You need to design your program so it prevents inappropriate actions by users. And make sure the owner account (which can be set up specifically for your application) does not have more privileges than it needs.
If you trust people who have "root" permission on the system(s) that this is installed on, you can rely on having a special user or group, and use setuid and/or setgid to prevent others from tampering with the file. This does, however, mean that the installer of the software will need to have root permission, so "any" user can't install the software, which in some circumstances may not be a good solution.
The better solution is really to either have a hash of the file stored in the file [plus some constant data or some such, so that the user can't just run sha1 modified-file and get the "right hash"], or encrypt the whole file.
The problem with BOTH of these methods is that you still can't rely on it 100% - someone with enough motivation and resources will figure out what the constant data is, and just calculate that as new hash after modifying the data in your file. And similarly, assuming your application knows how to decrypt the file, the application can be reverse engineered to find the encryption key and encryption method.
So you are fighting a "code war" (pun on cold war) against your "users".
There are commercial solutions available for license management (and that I have been the user of is FlexLM, but there are several others too). This is a little more work, and will probably cost a little bit in license fees, but you will save yourself a whole heap of potential headache if you use a commercial product.

Change Clickonce cache directory

We have been using ClickOnce deployment for some time now and all has been fine until recently. We have one of our clients that is now deleting their clients Documents and Settings directories which inturn is totally erasing our clickonce cache. From what I have seen, there is no way of setting an alternate location for this, but many of my references online were from 2005.
I was hoping someone may be able to provide a definitive answer as to whether or not they have changed this and there is a way to change the installation directory and if not, do you have any recommendation where I may be able to find a solution to this problem.
In then end, we would like the same Clickonce functionality regarding auto updates, however a way of letting the user choose where they want to install their files to. Any info would be great! Thanks!!
Dan
I found a post that seems to ask the same question as you do, and according to the answers it received, it is not possible to set the destination folder of a ClickOnce application.
Anyway, I think it's a reasonable assumption to make when developing an application for a client that the application data folder will not be deleted on an ad-hoc basis (unless this is a condition that has been known during the requirement gathering of the project).
If this client of yours doesn't have a very specific (and good) reason to remove the app data folders, I think you should just explain that "no, that's not going to work with our solution".

how-to: programmatic install on windows?

Can anyone list the steps needed to programatically install an application on Windows. Aside from copying the files where they need to be, what are the additional steps needed so that your app will be a first-class citizen in Windows (i.e. show up in the programs list, uninstall list...etc.)
I tried to google this, but had no luck.
BTW: This is for an unmanaged c++ application (developed in Qt), so I'd rather not involve the .net framework if I don't have to.
I highly recommend NSIS. Open Source, very active development, and it's hard to match/beat its extensibility.
To add your program to the Add/Remove Programs (or Programs and Features) list, add the following reg keys:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PROGRAM_NAME]
"DisplayName"="PROGRAM_NAME"
"Publisher"="COMPANY_NAME"
"UninstallString"="PATH_TO_UNINSTALL_PROGRAM"
"DisplayIcon"="PATH_TO_ICON_FILE"
"DisplayVersion"="VERSION"
"InstallLocation"="PATH_TO_INSTALLATION_LOCATION"
I think the theme to the answers you'll see here is that you should use an installation program and that you should not write the installer yourself. Use one of the many installer-makers, such as Inno Setup, InstallSheild, or anything else someone recommends.
If you try to write the installer yourself, you'll probably do it wrong. This isn't a slight against you personally. It's just that there are a lot of little details that an installer should consider, and a lot of things that can go wrong, and if you want to write the installer yourself, you're just going to have to get all those things right. That means lots of research and lots of testing on your part. Save yourself the trouble.
Besides copying files, installation tasks vary quite a bit depending on what your program needs. Maybe you need to put an icon on the Start menu; an installer tool should have a way to make that happen very easily, automatically filling in the install location that the customer chose earlier in the installation, and maybe even choosing the right local language for the shortcut's label.
You might need to create registry entries, such as for file associations or licensing. Your installer tool should already have an easy way to specify what keys and values to create or modify.
You might need to register a COM server. That's a common enough action that your installer tool probably has a way of specifying that as part of the post-file-copy operation.
If there are some actions that your chosen installer tool doesn't already provide for, the tool will probably offer a way to add custom actions, perhaps through a scripting language, or perhaps through linking external code from a DLL you would write that gets included with your installer. Custom actions might include downloading an update from a specific Web site, sending e-mail, or taking an inventory of what other products from your company are already installed.
A couple of final things that an installer tool should provide are ways to apply upgrades to an existing installation, and a way to uninstall the program, undoing all those installation tasks (deleting files, restoring backups, unregistering COM servers, etc.).
I've used Inno Setup to package my software for C++. It's very simple compared to heavy duty solutions such at InstallShield. Everything can be contained in a single setup.exe without creating all these crazy batch scripts and so on.
Check it out here: http://www.jrsoftware.org/isinfo.php
It sounds like you need to check out the Windows Installer system. If you need the nitty-gritty, see the official documentation. For news, read the installer team's blog. Finally, since you're a programmer, you probably want to build the installer as a programmer would. WiX 3.0 is my tool of choice - open source code, from Microsoft to boot. Start with this tutorial on WiX. It's good.
The GUI for innosetup (highly recommended) is Istool
You can also use the MSI installer built into Visual Studio, it's a steeper learning curve (ie is a pain) but is useful if you are installing software in a corporate environment.
To have your program show up in the Start program menu,
You would need to create folder
C:\Documents and Settings\All Users\Start Menu\Programs
and added a short cut to the program you want to launch.
(If you want your application be listed
directly in the Start menu, or in the programs submenu,
you would put your short cut in the respective directory)
To programically create a short cut you can use IShellLink
(See MSDN article).
Since you want to uninstall, that gets a lot more involved because you don't want to simply go deleting DLLs or other common files without checking dependencies.
I would recommend using a setup/installation generator, especially nowadays with Vista being so persnickety, it is getting rather complicated to roll your own installation
if you need anything more than a single executable and a start menu shortcut.
I have been using Paquet Builder setup generator for several years now.
(The registered version includes uninstall).
You've already got the main steps. One you left out is to install on the Start Menu and provide an option to create a desktop and/or quick launch icon.
I would encourage you to look into using a setup program, as suggested by Jeremy.