Question

I am accessing my assembly's configuration like this:

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = Assembly.GetExecutingAssembly().Location + ".config";
Configuration conf = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
AppSettingsSection appSettings = conf.AppSettings;

My .config file contains a section like this

<configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="CsDll.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
</configSections>
<connectionStrings>
    <add name="CsDll.Properties.Settings.SabreCAD" connectionString="A Connection string." />
    <add name="CsDll.Properties.Settings.StpParts" connectionString="Another connection string" />
</connectionStrings>
 <applicationSettings>
        <CsDll.Properties.Settings>
            <setting name="StpInsertSearchPath" serializeAs="Xml">
                <value>
                    <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                        <string>A string</string>
                        <string>Another string in the collection</string>

I can successfully read the connection strings including changes if I edit the .config file. So, I know I am connected to the correct file. But I cannot find that string collection inside of the appSettings object. It is is not in the .Settings KeyValueConfigurationCollection. Where do I find my string collection?

Was it helpful?

Solution

You should be access the items in the collection using this simpler syntax

foreach (string s in CsDll.Properties.Settings.Default.StpInsertSearchPath)
{
    Console.WriteLine(s);
}

EDIT:

The following code should do the trick

ExeConfigurationFileMap map = new ExeConfigurationFileMap(); 
map.ExeConfigFilename = Assembly.GetExecutingAssembly().Location + ".config"; 
Configuration conf = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); 
ConfigurationSectionGroup appSettingsGroup = conf.GetSectionGroup("applicationSettings");
ClientSettingsSection clientSettings = (ClientSettingsSection) appSettingsGroup.Sections["CsDll.Properties.Settings"];
ConfigurationElement element = clientSettings.Settings.Get("StpInsertSearchPath");
string xml = ((SettingElement)element).Value.ValueXml.InnerXml;
XmlSerializer xs = new XmlSerializer(typeof(string[]));
string[] strings = (string[])xs.Deserialize(new XmlTextReader(xml, XmlNodeType.Element, null));
foreach (string s in strings)
{
    Console.WriteLine(s);
}

There may be a shorter way, but this works for me.

OTHER TIPS

AppSettings and ConnectionStrings are both properties directly available on the ConfigurationManager.

However, applicationSettings and userSettings, which correspond to the familiar Settings.settings you can edit in the VS settings designer, are not so easy to get at. AppSettings is NOT the same as applicationSettings which is in an entirely different section of the config file in use.

You must use the mining approach above or a variant to get at applicationSettings and userSettings. Also, the applicationSettings will only update next time you start the application, if you are even able to write to them at all at runtime.

For example (cribbed from elsewhere - thank you):

public static string ReadSetting(string sectionGroupName, string sectionName, string settingName, Configuration config = null)
    {
        if (config == null)
            config = SharedConfigSettings;
        // Get sectionGroup
        var sectionGroup =
          config.GetSectionGroup(sectionGroupName);

        // Get section
        var section =
          (ClientSettingsSection)sectionGroup.Sections.Get(sectionName);
        // Get setting
        var setting = section.Settings.Get(settingName);
        // Read setting value
        return setting.Value.ValueXml.InnerText;
    }

and for another example (adaoted from many examples - thank you to the world):

///<summary>
    /// return the applicationSettings section 
    ///</summary>
    ///<returns></returns>
    public static ClientSettingsSection GetSettingsSection(ConfigurationSectionGroup group, string clientSectionName)
    {
        return (ClientSettingsSection)group.Sections[clientSectionName];
    }


    ///<summary>
    /// return the section settings collection
    ///</summary>
    ///<returns></returns>
    public static System.Configuration.SettingElementCollection GetSettingsCollection(ClientSettingsSection section)
    {
        return section.Settings;
    }

    ///<summary>
    /// return the connectionStrings section collection
    ///</summary>
    ///<returns></returns>
    public static System.Configuration.SettingElementCollection ConnectionStringsCollection()
    {
        return ((ClientSettingsSection)SharedConfigSettings.GetSection("connectionStrings")).Settings;
    }

    ///<summary>
    /// A collection of all the UserSettings in a SettingElementCollection
    ///</summary>
    ///<returns></returns>
    public static SettingElementCollection UserSettings()
    {
        return
            GetSettingsCollection(GetSettingsSection(GetSettingsSectionGroup(@"userSettings"),
                                                     @"MyAssembly.Properties.Settings"));
    }

    ///<summary>
    /// A collection of all the ApplicationSettings in a SettingElementCollection
    ///</summary>
    ///<returns></returns>
    public static SettingElementCollection ApplicationSettings()
    {
        return
            GetSettingsCollection(GetSettingsSection(GetSettingsSectionGroup(@"applicationSettings"),
                                                     @"MyAssembly.Properties.Settings"));
    }

Then, unfortunately you still have to deal with the SettingElement objects that are in the settings collection in these sections. Each one has to deserialized to the property Type unless it is a string e.g. for an applicationSettings SettingElement (one that cannot be dynamically updated at runtime):

(exerciser)

 var y = GetSettingsSection(GetSettingsSectionGroup(@"applicationSettings"), @"MyAssembly.Properties.Settings");
 var c = (y.Settings.Cast<SettingElement>().FirstOrDefault(s => s.Name == "WellKnownDirectories").Value).ValueXml
                .InnerXml; // the setting as Xml
 var xs = new XmlSerializer(typeof(string[]));
 var strings = (string[])xs.Deserialize(new XmlTextReader(c, XmlNodeType.Element, null));

foreach (string s in strings)
        {
            Console.WriteLine(s);
        }

For a string property it is easier (this example is essentially redundant with the first one above):

var s = (y.Settings.Cast<SettingElement>().FirstOrDefault(s => s.Name == "MyUserSettingName").Value).ValueXml
                .InnerText

All of these examples fiddled with applicationSettings. The same approach can work with userSettings with the addition of probably some save methods and so on, and you do need to keep track (more or less) of which of the several many config files are actually in play - main, roaming, or local.

Why am I doing this? Because two related applications and a common class library (or libraries) all need to use the same settings owned by one of the applications where the settings are visually managed. Has anyone solved this in a better way?

Thanks.

if it is a StringCollection you are trying to extract from the settings

var strings = (StringCollection) Properties.Settings.Default["StpInsertSearchPath"];

will accomplish as much with out the need for XmlSerializer

You connection strings are typically inside of the configuration manager's ConnectionStrings property. You should be able to access in a much simpler fashion through its static method.

string myConnectionString = ConfigurationManager.ConnectionStrings["connectioStringName"];

I believe you should use the tag "AppSettings" instead of "ApplicationSettings" in the .config file to enable the ConfigurationManager to access through the AppSettings property.

I don't know enough about how ConfigurationManager works to be sure this will solve your problem, but renaming it and removing that custom section group should allow AppSettings to work properly.

Edit Yes, it appears that ConfigurationManager's AppSettings property accesses the section named in the .config file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top