IanG on Tap

Ian Griffiths in Weblog Form (RSS 2.0)

Blog Navigation

April (2018)

(1 item)

August (2014)

(1 item)

July (2014)

(5 items)

April (2014)

(1 item)

March (2014)

(1 item)

January (2014)

(2 items)

November (2013)

(2 items)

July (2013)

(4 items)

April (2013)

(1 item)

February (2013)

(6 items)

September (2011)

(2 items)

November (2010)

(4 items)

September (2010)

(1 item)

August (2010)

(4 items)

July (2010)

(2 items)

September (2009)

(1 item)

June (2009)

(1 item)

April (2009)

(1 item)

November (2008)

(1 item)

October (2008)

(1 item)

September (2008)

(1 item)

July (2008)

(1 item)

June (2008)

(1 item)

May (2008)

(2 items)

April (2008)

(2 items)

March (2008)

(5 items)

January (2008)

(3 items)

December (2007)

(1 item)

November (2007)

(1 item)

October (2007)

(1 item)

September (2007)

(3 items)

August (2007)

(1 item)

July (2007)

(1 item)

June (2007)

(2 items)

May (2007)

(8 items)

April (2007)

(2 items)

March (2007)

(7 items)

February (2007)

(2 items)

January (2007)

(2 items)

November (2006)

(1 item)

October (2006)

(2 items)

September (2006)

(1 item)

June (2006)

(2 items)

May (2006)

(4 items)

April (2006)

(1 item)

March (2006)

(5 items)

January (2006)

(1 item)

December (2005)

(3 items)

November (2005)

(2 items)

October (2005)

(2 items)

September (2005)

(8 items)

August (2005)

(7 items)

June (2005)

(3 items)

May (2005)

(7 items)

April (2005)

(6 items)

March (2005)

(1 item)

February (2005)

(2 items)

January (2005)

(5 items)

December (2004)

(5 items)

November (2004)

(7 items)

October (2004)

(3 items)

September (2004)

(7 items)

August (2004)

(16 items)

July (2004)

(10 items)

June (2004)

(27 items)

May (2004)

(15 items)

April (2004)

(15 items)

March (2004)

(13 items)

February (2004)

(16 items)

January (2004)

(15 items)

Blog Home

RSS 2.0

Writing

Programming C# 5.0

Programming WPF

Other Sites

Interact Software

Why Writing Into .NET Application Configuration Files Is a Bad Idea

Thursday 25 November, 2004, 12:27 PM

I seem to write about this often enough in news groups and mailing lists that I thought I'd put it up here - that way I can just post a link next time...

.NET applications can have a configuration file associated with them. In web apps, the file is called web.config. For a normal Windows or console application, it is has the same name as the executable with .config tacked on the end. So if your app is called Foo.exe, you would put the configuration file in the same directory and call it Foo.exe.config. In Visual Studio .NET projects, the file will be called App.config - VS.NET copies it into your build output directory and changes the name appropriately.

.NET itself looks for certain settings inside this file. For example, the assembly resolver can be configured this way. It can also be used to store some application-specific settings in its <appSettings> element. Because of this, a frequently asked question emerges:

How do I write settings into the application configuration file at runtime?

The short answer is: "Don't do that."

The slightly more informative but still fairly succinct answer is: "You quite often can't, and even when you can you don't want to."

Here's the long answer.

Why the Config File Might Not Be Writable

The configuration file is stored in the same directory as the executable itself. It's pretty common for users not to have permission to write to this directory. Indeed that's just common sense and good practice - ensuring that the user doesn't have permission to write into directories where executables are stored prevents a lot of viruses, spyware, and other malware from wreaking havoc.

This is why the Program Files directory is configured not to allow normal users to write to it.

Unfortunately, not everyone runs as a normal user - lots of people run as administrators on their Windows machines. This is a shame as it means they are throwing away a lot of the protection Windows can offer them. Of course one of the reasons so many people run as administrators is because of crappy applications that attempt to write into their installation directories.

Don't make your application one of those crappy applications. Don't try and write into the directory where your application is installed, because if you do that, your program won't run properly unless the user is an administrator.

Of course there may be other reasons that the file isn't writable. If your application is deployed via HTTP, the configuration file will live on the web server, and you are unlikely to be able to modify it.

Why You Wouldn't Want to Write Into It Even If You Could

Let's suppose you've ignored the above, and have decided to write a crappy application that writes into the directory it runs from. (Welcome to Keith Brown's Hall of Shame by the way.) You still don't want to be writing user settings in there. (And there's no need to put application-wide settings there either.)

Lots of machines have multiple users. And not just terminal servers - all my home machines have multiple users because I'm not the only person who logs into them. They don't tend to have multiple simultaneous users, but that's not the point. I don't want someone else's configuration choices to affect my account.

For example, I have a separate login I use on my laptop for doing presentations. All of the fonts are configured to be extra large and legible. The resolution is set for a projector rather than the laptop's own screen. It would be hugely annoying if these things were configured on a per-machine basis, because I'd have to keep reconfiguring them, rather than simply being able to switch user accounts. (Actually ILDASM stores font settings in a machine-wide way, and it really bugs me.)

If you store user settings in the application configuration file, you will be storing one load of settings that apply to all users on the machine. Of course you could fix that by rolling your own mechanism to keep each user's settings isolated. But you'd be mad to build such a thing when there's already a perfectly good system for doing this built into Windows!

Where Should I Put This Information Then?

The user's profile directory is the appropriate place for user settings. Since there is a profile directory for each user, this keeps the settings separate. Moreover, if the profile is configured as a roaming profile, the user's settings will then follow them around the network as they log into various machines. And if they back up their Documents and Settings directory, your application's settings will be backed up as a part of that operation. What's not to like?

So how do you locate this directory? .NET makes that very easy, thanks to the System.Environment class:

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

That will return a string, containing the path of the Application Data subdirectory of the user's profile. (If you want to store data that does not become part of the roaming profile, use LocalApplicationData instead.) You should create a subdirectory named after your company, and inside that a subdirectory named after your program. (If you look inside your profile's Application Data directory, you'll see that this is the structure applications usually use.) You may also choose to put a version-specific subdirectory underneath the application name directory.

(If your code might need to run with partial trust, look at the Isolated Storage APIs. These are a bit more cumbersome than just creating files in the right directory, and create some funny-looking paths. But they have the considerable advantage of working in partial trust scenarios.)

Note that even if you want to store application-wide settings, you still don't have to write into the application installation directory. Just do this:

Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)

That returns a path for machine-wide settings. Not all users will have write access to this by the way, so be careful.

So What Exactly Is The Configuration File For Then?

The configuration file is really only for settings configured at deployment time. It can be used to deal with versioning issues with .NET components. And it's often used for connections strings - it's useful to be able to deploy an application to connect to a test or staging server, but this is not something you'd normally change in production once the application is deployed.

Copyright © 2002-2024, Interact Software Ltd. Content by Ian Griffiths. Please direct all Web site inquiries to webmaster@interact-sw.co.uk