In various installments in this series, I observed that file and registry access control lists (ACLs) are the source of most of the least privilege problems that mere users have to suffer. Usually that means that the application developer has stored application data in a protected area that's inaccessible to a member of the Users group, such as HKEY_LOCAL_MACHINE in the registry or c:\Program Files in the file system. You can avoid putting your users through this torture by storing things in the proper locations. Here are some of the many options:
- Put static program files in the application directory in c:\Program Files. This is the purpose of Program Files.
- Put static, read-only data files in the application directory in Program Files. The application uses these files but doesn't write to them as part of running the application (for example, app.config).
- Use isolated storage for secure, user-specific data. This is managed by the CLR and has restrictions based on the security policies set on the machine. But don't use isolated storage for data that the user might want to manipulate outside of your application—it isn't easy for a nontechnical user to find.
- If you must write to the registry, write to HKEY_CURRENT_USER rather than HKEY_LOCAL_MACHINE.
Application data has a whole other set of possibilities. This is the data that your application generates, uses, and updates during the course of running. It could be configuration settings, data read from a remote database and stored locally, or anything else that the application needs to store at runtime. You can obtain the full path for these directories using properties of the System.Windows.Forms.Application class in .NET. There are three properties of interest, each returning a different Application Data directory:
- CommonAppDataPath is the location of data shared among all users on
a machine. The default location is as follows:
C:\Documents and Settings\All Users\Application Data\CompanyName\ProductName\ProductVersion
Because each user has restricted rights, you must create at installation the subdirectory that your application will use.
- LocalUserAppDataPath is the data location used by local,
non-roaming users only. Here's the default:
C:\Documents and Settings\username\Local Settings\Application Data\CompanyName\ProductName\ProductVersion.
- UserAppDataPath is similar to LocalUserAppDataPath, except
that it can store data for both local and roaming users. This is the
C:\Documents and Settings\username\Application Data\CompanyName\ProductName\ProductVersion
In each of the paths returned, CompanyName, ProductName, and ProductVersion are all properties of Application object, which .NET reads from the assembly attributes, frequently stored in AssemblyInfo.vb or AssemblyInfo.cs in the default Visual Studio project templates. If you don't want to use either ProductName or ProductVersion, just strip these off of the path returned from the Application object property.
If your application creates and uses documents, it might make sense to store them in the user's My Documents directory. This is usually located here:
C:\Documents and Settings\[user]\My Documents
Note that the user can change that location, so don't assume that's where it's located. You can use code like this to get the full path for the current user's My Documents directory:
Dim sMyDocs as String = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
Making wise choices about where to store data is key to writing applications that mere users can use. And you really can survive development as a mere user.