So, I have been trying to write a tool to manage addition/updates to configuration
file like SomeApp.exe.config. This involves reading and writing to configuration files.
Using XML DOM is too low level when 2.0 provides System.Configuration namespace.
Here is the outcome of that effort. Thought I will share in view of the lack of documentation
from MS. Read/Write AppSettings wasnt hard. What I had problems with
was read/write custom ConfigurationSection

Here are a bunch of gotchas from this effort

  • If you are writing a configuration management app that wants to access random config
    files, you need to use ExeConfigurationFileMap and ConfigurationManager.OpenMappedExeConfiguration

  • When you read a configuration section from a source file and move
    it into some target file, you get an error “Cannot add a ConfigurationSection
    that already belongs to the Configuration
    “. I used reflection to get around
    this. I will show you how in a moment.

  • You can get raw xml configuration from ConfigurationSection using section.SectionInformation.GetRawXml().
    Likewise use SetRawXml to set this

  • When you load a config file using OpenMappedExeConfiguration,
    you get an in memory configuration which is “merged” and has sections from machine.config.
    You can check if a section came from the file you provided using section.ElementInformation.Source.Equals(source.FilePath)

So having got through that, here is how I did what I did

First off, load the source and target configs
>

//Load
Source


ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = “source.config”;
Configuration source = ConfigurationManager.OpenMappedExeConfiguration(map,ConfigurationUserLevel.None);

//Load
Target


map.ExeConfigFilename = “target.config”;
Configuration target = ConfigurationManager.OpenMappedExeConfiguration(map,
ConfigurationUserLevel.None);

Now
that we have the source and the target files we can start doing the real work

foreach (ConfigurationSection
section in source.Sections)
{
   //We
want to ensure that this guy came from the file we provided.. and not from say machine
config


   if (section.ElementInformation.Source
!=null &&
section.ElementInformation.Source.Equals(source.FilePath))
   {
      //Enumerator
is on AppSettings. So we update the appSettings


      if (section is AppSettingsSection)
      {
         foreach (KeyValueConfigurationElement
element in source.AppSettings.Settings)
         {
            target.AppSettings.Settings.Remove(element.Key);
            target.Save(ConfigurationSaveMode.Full, false);
            target.AppSettings.Settings.Add(element);
         }
       }
      //Enumerator
is on a custom section


      else

      {
         //Remove
from target and add from source. 


         target.Sections.Remove(section.SectionInformation.SectionName);
         //Just
paranoid.


         target.Save(ConfigurationSaveMode.Full, false);
         //Using
reflection to instantiate since no public ctor and the instance we hold is tied to
“Source”


         ConfigurationSection reflectedSection = Activator.CreateInstance(section.GetType()) as ConfigurationSection;
         reflectedSection.SectionInformation.SetRawXml(section.SectionInformation.GetRawXml());
         //Bug/Feature
in framework prevents target.Sections.Add(section.SectionInformation.Name, Section);


         target.Sections.Add(section.SectionInformation.Name,
reflectedSection);
      }
         ConfigurationManager.RefreshSection(section.SectionInformation.SectionName);
   }


 

>

 

Here is what the source looks like. It has one custom section and one appsettings
key value pair

<?xml
version=”1.0″ ?>
<configuration>
<configSections>
<section name=”MyCustomConfiguration” type=”Covarius.Configuration.MyCustomConfigurationSection,
Covarius.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=147be6ea50c5d416″
/>

</configSections>
<MyCustomConfiguration ConfigValue=”C:\Test2.ini” MyURL=”http://webservices.covarius.dev/testservice.asmx”/>

<appSettings>
    <add key=”CustomConfig”
value=”c:\blahCon.config”/>
</appSettings>
</configuration>

That was easy wasnt it. I have attached a utility AppConfigUpdater.exe. So you can
use it as a deployment tool to update config in say QA or PROD. Syntax is AppConfigUpdater
<sourcefile> <targetfile>

Comments welcome.

Linus Joseph

 >
Download
AppConfiUpdater.exe (16 KB)