13

Here's the idea I had:

I want a small executable to have an app.config file with multiple sections that are situated under the sectionGroup "applicationSettings" (not "appSettings", I don't need to write to the file). Each section would have a name corresponding to a module that should be loaded if set.

Here's an example:

   <configuration>
     <configSections>
       <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
         <section name="Executable" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
         <section name="FirstModule" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
       </sectionGroup>
     </configSections>
     <applicationSettings>
       <Executable>
         <setting name="MyFirstSetting" serializeAs="String">
           <value>My awesome feature setting</value>
         </setting>
       </Executable>
       <FirstModule path="path to the modules assembly">
         <setting name="ImportantSettingToTheModule" serializeAs="String">
           <value>Some important string</value>
         </setting>
       </FirstModule>
     </applicationSettings>
   </configuration>

Now if I define the FirstModule section, I want my application to load its assembly. If the section is not defined, the module should not be loaded. This should be true for not only one module but a not yet defined number of them.

So I basically need to find out about the defined sections at runtime. How would I do that?

In addition I want this to become a portable executable (= it has to run on Mono as well) that is backwards compatible to .NET 2.0.

It might be interesting to have a look at the project on GitHub (currently at this commit).

HaMster
  • 533
  • 1
  • 6
  • 17

1 Answers1

24

Take a look at the ConfigurationManager.OpenExeConfiguration function to load in your configuration file.

Then on the System.Configuration.Configuration class that you'll get back from ConfigurationManager.OpenExeConfiguration you'll want to look at the SectionGroups property. That'll return a ConfigurationSectionGroupCollection in which you'll find the applicationSettings section.

In the ConfigurationSectionGroupCollection there will be a Sections property which contains the Executable and FirstModule ConfigurationSection objects.

var config = ConfigurationManager.OpenExeConfiguration(pathToExecutable);
var applicationSettingSectionGroup = config.SectionGroups["applicationSettings"];
var executableSection = applicationSettingSectionGroup.Sections["Executable"];
var firstModuleSection = applicationSettingSectionGroup.Sections["FirstModule"];

You will want to check for null after getting the ConfigurationSectionGroupCollection object or ConfigurationSection objects. If they are null they don't exist in the configuraiton file.

You can also get the sections by using ConfigurationManager.GetSection

var executableSection = (ClientSettingsSection)ConfigurationManager
    .GetSection("applicationSettings/Executable");
var firstModuleSection = (ClientSettingsSection)ConfigurationManager
    .GetSection("applicationSettings/FirstModule");

Again, if the objects are null they don't exist in the configuration file.

To get a list of all the section names and groups you could do:

var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

// use the line below instead if you want to load an app.config for a
//   different application other than the one the code is running in
// var config = ConfigurationManager.OpenExeConfiguration(pathToExecutable);

var names = new List<string>();
foreach (ConfigurationSectionGroup csg in config.SectionGroups)
    names.AddRange(GetNames(csg));

foreach (ConfigurationSection cs in config.Sections)
    names.Add(cs.SectionInformation.SectionName);

private static List<string> GetNames(ConfigurationSectionGroup configSectionGroup)
{
    var names = new List<string>();

    foreach (ConfigurationSectionGroup csg in configSectionGroup.SectionGroups)
        names.AddRange(GetNames(csg));

    foreach(ConfigurationSection cs in configSectionGroup.Sections)
        names.Add(configSectionGroup.SectionGroupName + "/" + cs.SectionInformation.SectionName);

    return names;
}
JG in SD
  • 5,427
  • 3
  • 34
  • 46
  • That helped a lot, thank you very much. I would give two upvotes for directly referring to my example, but I can't... :( – HaMster Feb 19 '13 at 19:43
  • No problem, glad to help, you may want to see my latest edit. I included some information on `ConfigurationManager.GetSection`. Which if you don't need to perform any other actions on the configuration file, is usually the preferred way for accessing the configuration file. – JG in SD Feb 19 '13 at 20:26
  • 9
    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); - this will open the config for the current app. no need to know exe path. – timothy Sep 12 '14 at 08:36
  • Thanks @timothy! Excellent tip... saved me lots of searching. – Phil Nicholas Sep 22 '16 at 00:03
  • @JGinSD: I've used your code for solving my issue (stackoverflow.com/questions/68541684) but I still don't get it: why a recursive function call??? – Dominique Jul 27 '21 at 10:05
  • @Dominique `ConfigurationSectionGroup`s can be nested – Michael Sandler Feb 17 '23 at 11:58