views:

484

answers:

2

I'm playing around with .NET's configuration support (the ConfigurationManager class and related support classes). I would like to write an application that, once installed:

  • Has default settings in foo.exe.config (in Program Files).
  • The user may later override the settings with nondefault values which should be persisted.
  • The user's preferences should be persisted in the user's profile, since he shouldn't have write permissions to the Program Files directory.

The app should use the user's preferences when they're set, otherwise use the defaults.

It seems like this ought to be easy - it's a very common pattern. But my attempts at this are running into bumps and I'm wondering if I'm taking the right approach.

The following code produces the runtime exception "ConfigurationSection properties cannot be edited when locked".

using System;
using System.Configuration;

namespace DemoAppSettingsProblem
{
    class Program
    {
        static void Main(string[] args)
        {
            Configuration userConfig =
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
            if ( userConfig.AppSettings.Settings["foo"] != null )
                userConfig.AppSettings.Settings.Remove("foo");

            userConfig.AppSettings.Settings.Add("foo", "The string is foo.");

            userConfig.Save(ConfigurationSaveMode.Modified);    // exception!
        }
    }
}

The problem is that the .NET-defined <appSettings> section is declared with the default allowExeDefinition=MachineToApplication (see this nice post by Microsoft's Irena Kennedy). This prohibits the section from being written to the user's profile (either local or roaming).

So, I assume I need to define my own section, with allowExeDefinition=MachineToLocalUser. But as far as I can tell from the MSDN docs, that means I need to create my own configuration class, derived from ConfigurationSection. The examples there point me toward more work than I was expecting, which usually sets off my alarm bells that I'm doing something wrong.

Is it really this difficult to achieve this? Is there a simple way .NET provides to support this, or should I perhaps be taking a different approach altogether?

A: 

Assuming you're on .NET 2.0 and higher, have you checked out the "Settings" files? Those are being stored inside your app.config - application settings in <applicationSettings> sections, user-definable settings in <userSettings>, which incidentally have the allowExeDefinition=MachineToLocalUser setting you mentioned.

Maybe that could be an approach? Those user settings are a defined type, which you could definitely reuse under a different name, if needed ("mySettings").

Marc

marc_s
+1  A: 

I've used the settings feature, it writes user settings to the app config for you...

http://msdn.microsoft.com/en-us/library/aa730869(VS.80).aspx

MrTexas
This is EXACTLY what I was looking for. Thanks!
David Pope