Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write appSettings in external file

Tags:

c#

.net

config

I have a config file app.exe.config and appSettings section has something like this:

<configuration>
    <appSettings configSource="app.file.config" />
</configuration>

app.file.config file has something like this:

<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
  <add key="var1" value="value 1" />
  <add key="var2" value="value 2" />
  <add key="var3" value="value 3" />
</appSettings>

I need to edit var1, var2 and var3 at runtime and I have code like this:

Configuration config = ConfigurationManager.OpenExeConfiguration("...path\app.exe);

config.AppSettings.SectionInformation.ConfigSource = "app.file.config";

config.AppSettings.Settings["var1"].Value = "value 11";
config.AppSettings.Settings["var2"].Value = "value 22";
config.AppSettings.Settings["var3"].Value = "value 33";
config.Save(ConfigurationSaveMode.Modified);

ConfigurationManager.RefreshSection("appSettings");

When I run config.Save.... the file app.file.config has a appSettings node with an attribute "file". This attribute has the value to app.file.config

<appSettings file="app.file.config">
<add key="var1" value="value 1" />
  <add key="var2" value="value 2" />
  <add key="var3" value="value 3" />
</appSettings>

Now, if I try to load the config file, I have an exception with message "Unrecognized attribute 'file'. Note that attribute names are case-sensitive." in app.file.config.

If I delete the file attribute manually, the configuration file is loaded properly.

Any ideas?

How can avoid to write file attribute when I save config files.

Thanks

like image 554
J19 Avatar asked Dec 29 '14 15:12

J19


2 Answers

using an external config file is transparent for the application,

this part is o.k

</configuration>
    <appSettings configSource="app.file.config" />
</configuration>

and also this:

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

<appSettings>
  <add key="var1" value="value 1" />
  <add key="var2" value="value 2" />
  <add key="var3" value="value 3" />
</appSettings>

change your code to be like this:

Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
config.AppSettings.Settings["var1"].Value = "value 11";
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");

referring an external configuration file is transparent to the application, so you don't have to call it directly. you can use the default appSetting section in the configuration manager.

Good luck

like image 181
Tomer Klein Avatar answered Oct 18 '22 19:10

Tomer Klein


A more complete answer to prevent confusion:

Setup:

  1. Commandline project called 'app'
  2. app.exe.config file, App.config:

    <appSettings file="App.Settings.config"></appSettings>
    
  3. App.Settings.config file with 'Copy to Output Directory'= 'Copy Always'

    <?xml version="1.0" encoding="utf-8"?>
    <appSettings>
      <add key="test" value="OVERRIDDEN"/>
    </appSettings>
    
  4. Program.cs:

    static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Local Config sections");
            var exepath = (new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase)).LocalPath;
            Configuration config = ConfigurationManager.OpenExeConfiguration(exepath);
    
            config.AppSettings.SectionInformation.ConfigSource = "App.Settings.config";
    
            Console.WriteLine("BEFORE[test]=" + config.AppSettings.Settings["test"].Value);
            Console.WriteLine($"BEFORE[testExternalOnly]={config.AppSettings.Settings["testExternalOnly"]?.Value}");
    
            //to avoid: Error CS0266
            //Explicitly cast 'System.Configuration.AppSettingsSection'
            AppSettingsSection myAppSettings = (AppSettingsSection)config.GetSection("appSettings");
    
            myAppSettings.Settings["test"].Value = "NEW";
            if (!myAppSettings.Settings.AllKeys.Contains("testExternalOnly"))
                myAppSettings.Settings.Add("testExternalOnly", "NEWEXTERNAL");
    
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
    
            //Read updated config
            Console.WriteLine("AFTER[test]=" + config.AppSettings.Settings["test"].Value);
            Console.WriteLine("AFTER[testExternalOnly]=" + config.AppSettings.Settings["testExternalOnly"].Value);
    
            Console.WriteLine("AFTER CONFIG EXTERNAL FILE: " + System.IO.File.ReadAllText("App.Settings.config"));
    
            Console.WriteLine("AFTER CONFIG FILE: " + System.IO.File.ReadAllText(System.AppDomain.CurrentDomain.FriendlyName + ".config"));
    
    
            //Shut current config
            config = null;
    
            //Open config
            config = ConfigurationManager.OpenExeConfiguration(exepath);
            config.AppSettings.SectionInformation.ConfigSource = "App.Settings.config";
    
            Console.WriteLine("AFTER[test]=" + config.AppSettings.Settings["test"].Value);
            Console.WriteLine("AFTER[testExternalOnly]=" + config.AppSettings.Settings["testExternalOnly"].Value);
    
            Console.WriteLine("AFTER CONFIG EXTERNAL FILE: " + System.IO.File.ReadAllText("App.Settings.config"));
    
            Console.WriteLine("AFTER CONFIG FILE: " + System.IO.File.ReadAllText(System.AppDomain.CurrentDomain.FriendlyName + ".config"));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.WriteLine("press the ENTER key to end");
        Console.ReadLine();
    
    }
    

This will result in App.Settings.config file updated to be on the filesystem as:

<?xml version="1.0" encoding="utf-8"?>
<appSettings>
  <add key="test" value="NEW" />
  <add key="testExternalOnly" value="NEWEXTERNAL" />
</appSettings>
like image 22
OzBob Avatar answered Oct 18 '22 20:10

OzBob