I’ve been working on a small application for a client that saves records in a database. I’m building it to run on .NET 3.5 using Visual Studio 2008. Only one table was needed, but the data needed to be easily accessible for importation into Word and Excel by users with no programming or database abilities. As a result, I chose to use a Microsoft Access 2007 database file. I could have used Microsoft SQL Server Express, but then I would have had to add the merge files to my installer and force the user to cope with that secondary installation. In addition, using data in an Access database is generally easier for nonsavvy users, simply because Microsoft has made it so.
The only downside of using Access is that you have to put the file somewhere. In the old days of insecure operating systems, that was easy; put it wherever you want. These days, it presents more of a challenge, for a couple of reasons.
Installation vs. Execution
With Windows XP, Vista and 7, you have to take into consideration that the user who installs the program may not be the user who runs the program. Frequently, the program will be installed by a user with administrative rights (sometimes even the Administrator account). This means that the file can be written to most any location. However, the program will, assuming that the PC is configured to run securely, be run by a user with fewer rights. As a result, they may not be able to write to or even read the file. Even if only one user will be running the program, you won’t necessarily know in advance which it will be, so you have to still worry about the location.
The Shared Documents Option
One way to handle this is to put the file into the Shared Documents folder. That has several problems, though.
- Visual Studio does not have a predefined folder location for Shared Documents, and you can’t hard-code it, since the location depends on the version of Windows. This thread on StackOverflow provides a solution.
- Even if you get the file into Shared Documents, by default only members of the Administrator and Power User groups (Administrators only on Windows 7) have write permission. You’ll need to either be sure that all users who are going to be running the program are members of that group, or you have to change the default permissions for your file.
The Single User Option
In the event that the program will be used by a single user, you can always either drop the file into the Application Data directory (under a subfolder that you create, of course) or into their My Documents folder. The former is better option unless:
- The user needs to be able to find the file in order to use it in another program (e.g. it’s an Access database and they may need to pull the data into Word or Excel) or another instance of the program on another PC (e.g. synchronizing data between two copies of the database).
- They might need to manage multiple such files, each containing different information (e.g. personal vs. business contacts), including copying and deleting them.
If you can be sure that the program will be used under the same account that installed it, you can use one of the built-in options. If not, then you may have to configure your program to prompt the user for a location to create the file. You can then either programmatically create an empty file or you can copy a blank file from the installation directory and update the permissions as needed.
Why It’s Hard
Partly this is difficult because the need for tighter security has narrowed down the choices available to programmers. Generally, this is a good thing. Another part of the problem is that apparently some people at Microsoft think that having shared files is a bad idea and have avoided making it easier. This particular post was written by Raymond Chen, a long-time Microsoft employee and programmer. When I read this posting and the attendant comments, I had a hard time believing that I was reading something written by actual, professional programmers. It reads more a like a screed from an academic who only knows theory. The post and many of the comments classify this needed functionality as a security hole. Really? Certainly there are security risks in having a file shared by multiple users, but there are security risks in turning a computer on. The trick is to balance the risk against the needed functionality. Mr. Chen even suggested writing a service to control access to the data in the file. That might be a reasonable suggestion for some scenarios, but it’s a lot of work and would be overkill for most small applications. In my particular scenario, it’s also unnecessary, as the Access database driver already takes care of that.
My problem with their statements is that they’re saying that a particular approach is always bad, in all cases. There’s no apparent cost/benefit analysis. How do they know what the requirements of any random project are and how the usage scenario affects the security risk analysis? They don’t.
Unfortunately, it’s fairly common for programmers to make up their minds that some practice is bad and thus should never be used. Google multiple inheritance for a good example. Even practices that are rightly considered generally bad can be useful in certain circumstances. Examples:
- Denormalized data can be useful when speed is paramount.
- I think that using “i” as a variable name is okay if it’s an array index declared in the loop’s scope.
- I’m still waiting for someone to present a C or C++ algorithm using “goto” that wouldn’t be better written another way, but I acknowledge that might happen one day.
Binary thinking (it’s either good or bad) does not reflect the real world and leads to bad decisions.
Perhaps these particular programmers are used to the world of large, corporate applications where it would be assumed that if one were using a database, it would be an instance of SQL Server. Perhaps they’ve been burned too many times by bad security practices. I don’t know. I do know that I can think of many types of applications that need to share data among users. A subset of those applications are likely to be small, simple applications whose use cases, target users, development budget, etc. may not allow for complex architecture in order to maximize the security of that data. For this subset, looser security and simplicity may be the optimal solution. Microsoft should recognize that and support those cases by providing the necessary options in Visual Studio. If they want to cover their butts, they can release white papers discussing the pros and cons, add warnings to Visual Studio, etc.