views:

1606

answers:

5

I would like to override the use of the standard app.config by passing a command line parameter. How do I change the default application configuration file so that when I access ConfigurationManager.AppSettings I am accessing the config file specified on the command line?

Edit:

It turns out that the correct way to load a config file that is different than the name of the EXE plus .config is to use OpenMappedExeConfiguration. E.g.

        ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
        configFile.ExeConfigFilename = Path.Combine(Environment.CurrentDirectory, "Shell2.exe.config");
        currentConfiguration = ConfigurationManager.OpenMappedExeConfiguration(configFile,ConfigurationUserLevel.None);

This partially works. I can see all of the keys in the appSettings section but all the values are null.

A: 

A batch file that copies your desired configuration file to appname.exe.config and then runs the appname.exe.

kenny
Thanks for all of the support guys and gals. While you may not like it, it works. Lately, my approach is a -c=file.config and a generic console app and an Darrel's approach. I still have the generic console app copy the theapp.exe.config file to theapp.exe, to fool .NET.
kenny
A: 

This is not exactly what you are wanting... to redirect the actual ConfigurationManager static object to point at a different path. But I think it is the right solution to your problem. Check out the OpenExeConfiguration method on the ConfigurationManager class.

If the above method is not what you are looking for I think it would also be worth taking a look at using the Configuration capabilities of the Enterprise Library framework (developed and maintained by the Microsoft Patterns & Practices team).

Specifically take a look at the FileConfigurationSource class.

Here is some code that highlights the use of the FileConfigurationSource from Enterprise Library, I believe this fully meets your goals. The only assembly you need from Ent Lib for this is Microsoft.Practices.EnterpriseLibrary.Common.dll.

static void Main(string[] args)
{
    //read from current app.config as default
    AppSettingsSection ass = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings;

    //if args[0] is a valid file path assume it's a config for this example and attempt to load
    if (args.Length > 0 && File.Exists(args[0]))
    {
        //using FileConfigurationSource from Enterprise Library
        FileConfigurationSource fcs = new FileConfigurationSource(args[0]);
        ass = (AppSettingsSection) fcs.GetSection("appSettings");
    }

    //print value from configuration
    Console.WriteLine(ass.Settings["test"].Value);
    Console.ReadLine(); //pause
}
spoon16
The weird thing about this example is that it will load the default configuration file. If I change the exePath to be something else the OpenExeConfiguration fails.
Darrel Miller
I am going to get you a code sample in the next 20 minutes or so, but I went ahead and updated with a potential alternative.
spoon16
Darrel Miller
All you need is one EntLib assembly, you don't need the full thing and you don't need any extra configuration (which is pretty typical of other aspects of Ent Lib).
spoon16
Thanks for your effort, but if I can avoid taking a dependency on Entlib (V1, 2, 3, 3.1, 4, etc) I am going to.
Darrel Miller
Understood, this method does work quite well though :)
spoon16
+1  A: 

I needed to do this for an app of mine as well, and dealing with the standard config objects turned into such a freakin' hassle for such a simple concept that I went this route:

  1. Keep multiple config files in XML format similar to app.config
  2. Load the specified config file into a DataSet (via .ReadXML), and use the DataTable with the config info in it as my Configuration object.
  3. So all my code just deals with the Configuration DataTable to retrieve values and not that craptastically obfuscated app config object.

then I can pass in whatever config filename I need on the command line and if one isn't there - just load app.config into the DataSet.

Jeezus it was sooo much simpler after that. :-)

Ron

Ron Savage
I hear you. I keep waiting for the day when I realize, oh that's the advantage of using .config files. That day has not come.
Darrel Miller
+6  A: 

So here is the code that actually allows me to actually access the appSettings section in a config file other than the default one.

        ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
        configFile.ExeConfigFilename = Path.Combine(Environment.CurrentDirectory, "Alternate.config");
        Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFile,ConfigurationUserLevel.None);

        AppSettingsSection section = (AppSettingsSection)config.GetSection("appSettings");
        string MySetting = section.Settings["MySetting"].Value;
Darrel Miller
Good solution, thanks for sharing.
spoon16
A: 

This is the relevant part of the source for app that uses default config and accepts override via command line:

Get current or user config into the Config object

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
string defCfgName = Environment.GetCommandLineArgs()[0] + ".config";

if (arg.Length != 0)
{
 string ConfigFileName = arg[0];
 if (!File.Exists(ConfigFileName))
  Fatal("File doesn't exist: " + ConfigFileName, -1);                
 config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = ConfigFileName }, ConfigurationUserLevel.None);
}
else if (!File.Exists(defCfgName)) Fatal("Default configuration file doesn't exist and no override is set." , -1);

Use the config object

AppSettingsSection s = (AppSettingsSection)config.GetSection("appSettings");
KeyValueConfigurationCollection a = s.Settings;
ConnectionString = a["ConnectionString"].Value;
majkinetor