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
//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