47

This is my App.Config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="lang" value="English"/>
  </appSettings>
</configuration>

With this code I make the change

lang = "Russian";
private void Main_FormClosing(object sender, FormClosingEventArgs e)
{
     System.Configuration.ConfigurationManager.AppSettings.Set("lang", lang);
}

But it not change. What I'm doing wrong?

Philipp M
  • 1,877
  • 7
  • 27
  • 38
a1204773
  • 6,923
  • 20
  • 64
  • 94
  • 1
    possible duplicate of [Write values in app.config file](http://stackoverflow.com/questions/4758598/write-values-in-app-config-file) – nawfal Feb 10 '14 at 09:23

9 Answers9

97

AppSettings.Set does not persist the changes to your configuration file. It just changes it in memory. If you put a breakpoint on System.Configuration.ConfigurationManager.AppSettings.Set("lang", lang);, and add a watch for System.Configuration.ConfigurationManager.AppSettings[0] you will see it change from "English" to "Russian" when that line of code runs.

The following code (used in a console application) will persist the change.

class Program
{
    static void Main(string[] args)
    {
        UpdateSetting("lang", "Russian");
    }

    private static void UpdateSetting(string key, string value)
    {
        Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        configuration.AppSettings.Settings[key].Value = value;
        configuration.Save();

        ConfigurationManager.RefreshSection("appSettings");
    }
}

From this post: http://vbcity.com/forums/t/152772.aspx

One major point to note with the above is that if you are running this from the debugger (within Visual Studio) then the app.config file will be overwritten each time you build. The best way to test this is to build your application and then navigate to the output directory and launch your executable from there. Within the output directory you will also find a file named YourApplicationName.exe.config which is your configuration file. Open this in Notepad to see that the changes have in fact been saved.

Kevin Aenmey
  • 13,259
  • 5
  • 46
  • 45
  • 1
    How I can make the change then? – a1204773 Jun 22 '12 at 02:50
  • 1
    System.Configuration.ConfigurationManager.AppSettings[0] will not do nothing alone... Please fill the code – a1204773 Jun 22 '12 at 02:53
  • 1
    So I must write System.Configuration.ConfigurationManager.AppSettings[0] = lang? Because that give me error – a1204773 Jun 22 '12 at 02:56
  • 1
    I copied your code and run on VS 2012 c# 4.5 , it isn't working. I did check the bin/debug folder config file. It works only when I add the "configFileMap" as given in accepted answer – Gopi Mar 19 '15 at 09:55
  • 1
    It doesn't save permanently. When I debug I can see the value is changed but after complete execution, previous value is restored. – Gopi Jun 03 '15 at 18:40
  • 4
    For more robust code you could add a test if the key already exists: `if (configuration.AppSettings.Settings[key] == null) configuration.AppSettings.Settings.Add(key, value); else configuration.AppSettings.Settings[key].Value = value;` – huha May 10 '16 at 13:12
  • 1
    Nice Major Point. – yu yang Jian Jul 26 '17 at 02:07
52

You cannot use AppSettings static object for this. Try this

string appPath = System.IO.Path.GetDirectoryName(Reflection.Assembly.GetExecutingAssembly().Location);          
string configFile = System.IO.Path.Combine(appPath, "App.config");
ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap();         
configFileMap.ExeConfigFilename = configFile;          
System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);

config.AppSettings.Settings["YourThing"].Value = "New Value"; 
config.Save(); 
fenix2222
  • 4,602
  • 4
  • 33
  • 56
13

when use "ConfigurationUserLevel.None" your code is right run when you click in nameyourapp.exe in debug folder. .
but when your do developing app on visual stdio not right run!! because "vshost.exe" is run.

following parameter solve this problem : "Application.ExecutablePath"

try this : (Tested in VS 2012 Express For Desktop)

Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
config.AppSettings.Settings["PortName"].Value = "com3";
config.Save(ConfigurationSaveMode.Minimal);

my english not good , i am sorry.

Amin Ghaderi
  • 1,006
  • 13
  • 22
7

That worked for me in WPF application:

string configPath = Path.Combine(System.Environment.CurrentDirectory, "YourApplication.exe");
Configuration config = ConfigurationManager.OpenExeConfiguration(configPath);
config.AppSettings.Settings["currentLanguage"].Value = "En";
config.Save();
StepUp
  • 36,391
  • 15
  • 88
  • 148
3
    private static string GetSetting(string key)
    {
        return ConfigurationManager.AppSettings[key];
    }

    private static void SetSetting(string key, string value)
    {
        Configuration configuration =
            ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        configuration.AppSettings.Settings[key].Value = value;
        configuration.Save(ConfigurationSaveMode.Full, true);
        ConfigurationManager.RefreshSection("appSettings");
    }
fiaharon
  • 391
  • 3
  • 6
  • 3
    You may not want to save the config in ConfigurationSaveMode.Full. This will ad a ton of stuff to your app.config that you do not want. The rest is good. – Jeremy Jun 19 '15 at 05:43
  • 1
    You may also want to combine with the `Application.ExecutablePath` option for calling `OpenExeConfiguration`, as mentioned in @Amin Ghaderi's answer – mcw May 11 '16 at 13:45
3

In addition to the answer by fenix2222 (which worked for me) I had to modify the last line to:

config.Save(ConfigurationSaveMode.Modified);

Without this, the new value was still being written to the config file but the old value was retrieved when debugging.

djmcghin
  • 61
  • 4
2

For a .NET 4.0 console application, none of these worked for me. So I modified Kevn Aenmey's answer as below and it worked:

private static void UpdateSetting(string key, string value)
{
    Configuration configuration = ConfigurationManager.
        OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
    configuration.AppSettings.Settings[key].Value = value;
    configuration.Save();

    ConfigurationManager.RefreshSection("appSettings");
}

Only the first line is different, constructed upon the actual executing assembly.

James John McGuire 'Jahmic'
  • 11,728
  • 11
  • 67
  • 78
2

Thanks Jahmic for the answer. Worked properly for me.

another useful code snippet that read the values and return a string:

public static string ReadSetting(string key)
    {
        System.Configuration.Configuration cfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        System.Configuration.AppSettingsSection appSettings = (System.Configuration.AppSettingsSection)cfg.GetSection("appSettings");
        return appSettings.Settings[key].Value;

    }
2

To update entries other than appsettings, simply use XmlDocument.

public static void UpdateAppConfig(string tagName, string attributeName, string value)
{
    var doc = new XmlDocument();
    doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
    var tags = doc.GetElementsByTagName(tagName);
    foreach (XmlNode item in tags)
    {
        var attribute = item.Attributes[attributeName];
        if (!ReferenceEquals(null, attribute))
            attribute.Value = value;
    }
    doc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
}

This is how you call it:

Utility.UpdateAppConfig("endpoint", "address", "http://localhost:19092/NotificationSvc/Notification.svc");

Utility.UpdateAppConfig("network", "host", "abc.com.au");

This method can be improved to cater for appSettings values as well.

Baz Guvenkaya
  • 1,482
  • 3
  • 17
  • 26