ConfigurationManager use

1.1k views Asked by At

I wrote the following code to get ConfigurationManager data, to update it:

private static void UpdateConfigurationFile()
{
#if DEBUG
    string applicationName =
        Environment.GetCommandLineArgs()[0];
#else 
   string applicationName =
  Environment.GetCommandLineArgs()[0]+ ".exe";
#endif

    string exePath = System.IO.Path.Combine(
        Environment.CurrentDirectory, applicationName);

    // Get the configuration file. The file name has 
    // this format appname.exe.config.
    System.Configuration.Configuration config =
      ConfigurationManager.OpenExeConfiguration(exePath);

    string server = ConfigurationManager.AppSettings["server"];
}

At the end of the code, server is null.

The XML has the corresponding server code:

<applicationSettings>
    <forLiDAR.Properties.Settings>
        <setting name="Server" serializeAs="String">
            <value>localhost</value>
        </setting>

What am I doing wrong?

1

There are 1 answers

7
G.Y On

Ok, I have a solution to your problem.

Not easy to explain as it is not really your fault, VS has a bug that is being dragged with it for years now.

So lets take it step-by-step:

  1. Adding settings by using the right-click on project and going to settings tab - bad path to follow.. here is why:

If we follow the documentation, all we have to do is:

Properties.Settings.Default.Server = "Now I'm something different than localhost";
Properties.Settings.Default.Save();

No need to OpenExeConfigration or anything else , just those two lines! and .NET like a charm should be able to save the new setting into the configuration file.. except that it don't :) Instead it shouts 'Configuration System failed to initialize'!!

So.. we think "alright, they didn't cover it all in documentation.. lets add what we think is missing.." and so we add:

var exePath = System.IO.Path.Combine(Environment.CurrentDirectory, "ConsoleApplication58.vshost.exe.config");
var config = ConfigurationManager.OpenExeConfiguration(exePath);
var oldSetting = config.AppSettings.Settings["Server"].Value;

And we will get ... another exception - null reference this time. So we ask - "what is going there?!" and from debug we add watch for 'config.AppSettings.Settings' and to our horror we see that .NET actually trying to tell us "There is no spoon.." (or settings count is 0)

So at this point we can conclude this crap is definitely not working with application that use AppConfig.. but it might work with applications that use WebConfig - I didn't test that. (oh, just to make it clear:'This crap' means adding settings file by using the right-click on the project menu and going to settings tab)

  1. Ok... let's try the other method to do that which is Adding a setting file from Add New Item menu, its default filename is going to be 'settings1.settings' and it is going to reside under the general project folder name and not the properties as before.

So I did that too and tested the following lines:

var oldSetting = Settings1.Default.Server;
Settings1.Default.Server = "localhost2";
Settings1.Default.Save();

This worked - but I need to tell you that the 'Scope' has to be 'user' and not Application.. if its 'application' the setting will not have a setter.. and where did it save the information? in the AppData folder for that user.. which is logical.

This of course means that in order to check manually while you debug what was saved you need to go the configuration file of your app which resides in the AppData folder and not in your debug/bin folder.

  1. But all of this is of course not what you asked for... Because you want to save an 'application' scope setting - right? Well.. you can't - they are not designed for that. You can read here: https://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx

The ApplicationSettings class doesn't support saving settings to the app.config file. That's very much by design, apps that run with a properly secured user account (think Vista UAC) do not have write access to the program's installation folder.

You can fight the system with the ConfigurationManager class. But the trivial workaround is to go into the Settings designer and change the setting's scope to User. If that causes hardships (say, the setting is relevant to every user), you should put your Options feature in a separate program so you can ask for the privilege elevation prompt. Or forego using a setting.

So, last I will try to show you how your app should look like:

namespace ConsoleApplication58
{
    class Program
    {
        static void Main(string[] args)
        {
            UpdateConfigurationFile();
        }

        private static void UpdateConfigurationFile()
        {
            var oldSetting = Settings1.Default.Server; //to get the current setting if you want..
            Settings1.Default.Server = "localhost2"; //to change the setting.
            Settings1.Default.Save(); //to save settings.
        }
    }
}

And provided you add Settings1.Settings file as I mentioned, this is how appConfig could look like:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="ConsoleApplication58.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
    </startup>

    <userSettings>
        <ConsoleApplication58.Settings1>
            <setting name="Server" serializeAs="String">
                <value>localhost</value>
            </setting>
        </ConsoleApplication58.Settings1>
    </userSettings>
</configuration>

As requested in the comment here is a link to the bug report:
Configuration in the App.Config and ApplicationSettings