I have a windows forms application. (Visual Studio 2005)
A simple form with a button on it.
Here is the code
private void btnTestButton_Click(object sender, EventArgs e)
{
ConfigurationManager.AppSettings["TestSetting"] = "TestValue";
string res = ConfigurationManager.AppSettings["TestSetting"];
MessageBox.Show(res);
}
I step through the program in debugging mode.
The MessageBox shows "TestValue" as it should. This proves that the application setting was saved, somewhere.
I keep the program running. I search my hard drive for all files named *config*, modified within 1 day, that contain "TestSetting" or "TestValue". There are none. I search my hard drive for any modified file, containing "TestSetting" or "TestValue". There are none.
It seems that the saved value exists only in memory.
I close the app, re-open it. Now I run this instead. The same as before but no assignment.
private void btnTestButton2_Click(object sender, EventArgs e)
{
string res = ConfigurationManager.AppSettings["TestSetting"];
MessageBox.Show(res);
}
The value comes back null. Therefore, the application setting was not saved.
What good are the application settings, if you can't save them
Do I have to "publish" the app before I can get a version that will actually save somewhere. That makes it hard to test. Anyway, I tried it and that did not work either.
By the way, are application settings saved using ConfigurationManager.AppSettings, do they end up in the <userSettings> section, or do they end up in the <applicationSettings> section
What I am trying to do is simple. Let the user type in some value into a text box. Then save it for him, so that when he closes the program and comes back, it will be there, so that he does not have to type it again. I cannot get that most simple thing to work.
Thanks for any help.

appSettings, where do they save?
B Word
The documentation is very unclear.
There is one doc out there that references "CustomSection" without first declaring it
http://msdn2.microsoft.com/en-us/library/system.configuration.configuration.aspx
In another document, they show CustomSection as custom-written class derived from the abstract base class System.Configuration.ConfigurationSection.
The idea is that the system will serialize/deserialize your custom class to/from the configuration file, using XML serialization. You access values in the configuration file by accessing values in your custom class. It is sophisticated but overly complex if I just want to write a string value based on its name.
As far as ConfigurationManager.AppSettings is concerned, that still won't save for me. You can find where it saves the file, through the following property
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.None);
MessageDlg.Show(config.FilePath);
So at least that part is resolved and it would save to \bin\debug\[MyApplication].config, as you suggested, if it actually saved, but it will not save.
I am going to try the "CustomSection" solution and see if I can get that to work.
bill mccandless
I got it working using the "CustomSection" style of saving configuration settings.
Something like 40 lines of code, to do what we used to do with about 3 lines of code working with INI files.
Here is the solution that worked.
This class represents the object that I am going to serialize and save to the configuration file. This class is actually a sub-class within a higher-level form class.
public class CustomSection : ConfigurationSection
{
public CustomSection() { }
[ConfigurationProperty("ServerURL", DefaultValue = "http://",
IsRequired = false, IsKey = false)]
public string ServerURL
{
get
{
return (string)this["ServerURL"];
}
set
{
this["ServerURL"] = value;
}
}
[ConfigurationProperty("Alias", DefaultValue = "",
IsRequired = false, IsKey = false)]
public string Alias
{
get
{
return (string)this["Alias"];
}
set
{
this["Alias"] = value;
}
}
[ConfigurationProperty("Login", DefaultValue = "",
IsRequired = false, IsKey = false)]
public string Login
{
get
{
return (string)this["Login"];
}
set
{
this["Login"] = value;
}
}
}
Notice all the ConfigurationProperty attributes. Those are needed to set the default values for the attribute; otherwise you will get nulls when reading the value for the first time.
When the form opens (the "Shown" event), I call this procedure to initialize values in the various text boxes on the form.
private void LoadAllSettings()
{
string CustSettingName = "MainFormSettings";
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.None);
CustomSection custSection = (config.Sections[CustSettingName]
as CustomSection);
if (custSection == null)
{
custSection = new CustomSection();
config.Sections.Add(CustSettingName, custSection);
}
edURL.Text = custSection.ServerURL;
edAlias.Text = custSection.Alias;
edLogin.Text = custSection.Login;
edPwd.Text = "";
}
If custSection is null, then I must initialize it using the constructor, in order to pick up the default values. However, I do not have to save here as I do not save until the user attempts his connection.
When the user presses the button to connect to the web service, and if the connection is successful, then I save the values (minus the password) to the configuration file. I do not save the password as the configuration file is not secure.
Here is the code for saving the configuration settings
private void SaveAllSettings()
{
string CustSettingName = "MainFormSettings";
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.None);
CustomSection custSection = (config.Sections[CustSettingName]
as CustomSection);
if (custSection == null)
{
custSection = new CustomSection();
config.Sections.Add(CustSettingName, custSection);
}
custSection.ServerURL = edURL.Text;
custSection.Alias = edAlias.Text;
custSection.Login = edLogin.Text;
custSection.SectionInformation.ForceSave = true;
config.Save(ConfigurationSaveMode.Modified);
}
It works. Everything gets saved to the configuration file [ApplicationName].config in the bin/debug folder as thus
< xml version="1.0" encoding="utf-8" >
<configuration>
<configSections>
<section name="MainFormSettings" type="ClientApp.MainForm+CustomSection, BenchmarkClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<MainFormSettings ServerURL="http://www.myworld.com" Alias="myalias"
Login="mylogin" />
</configuration>
We can see the new section listed in <configSections> and the new values written to the <MainFormSettings section.
Wow. Now let us contrast that with the "old school" way of using the INI file
private void SaveAllSettings()
{
string MySection = "MainFormSettings";
IniFile ini = new IniFile("MyApp.ini");
ini.WriteString(MySection, "ServerURL", edURL.Text);
ini.WriteString(MySection, "Alias", edAlias.Text);
ini.WriteString(MySection, "Login", edLogin.Text);
}
private void LoadAllSettings()
{
string MySection = "MainFormSettings";
IniFile ini = new IniFile("MyApp.ini");
edURL.Text = ini.ReadString(MySection, "ServerURL", "http://");
edAlias.Text = ini.ReadString(MySection, "Alias", "");
edLogin.Text = ini.ReadString(MySection, "Login", "");
}
About 10 lines of code in the "old school" way versus about 40 in the "new school" way. That is 30 additional lines of code to write and debug. Guys, this is progress.
mmresnick
When working in debug mode you might find it as [Project Name].exe.config in [MyApplication]\bin\debug
When you build your project you might find it as [Project Name].exe.config in [MyApplication]\bin\release
When working in the IDE you can add an app.config file to your WindowsApplication. One would think it would create the file if you didn't already add it to your project
If you can't find it anywhere else you might try machine.config and I would guess that it should also be visible on the settings tab of the applications properties.
Bob Arnson MSFT
OK, rewrote the thing using ApplicationSettingsBase.
The syntax is more tolerable now.
We create a new class derived from ApplicationSettingsBase.
sealed class TMainFormSettings : ApplicationSettingsBase
{
[UserScopedSetting()]
[DefaultSettingValueAttribute("http://")]
public string ServerURL
{
get
{
return (string)this["ServerURL"];
}
set
{
this["ServerURL"] = value;
}
}
[UserScopedSetting()]
[DefaultSettingValueAttribute("")]
public string Alias
{
get
{
return (string)this["Alias"];
}
set
{
this["Alias"] = value;
}
}
[UserScopedSetting()]
[DefaultSettingValueAttribute("")]
public string Login
{
get
{
return (string)this["Login"];
}
set
{
this["Login"] = value;
}
}
}
I declare the class "sealed" for no particular reason other than the help file had it that way. The class definition looks almost, but not quite as ugly as the previous ConfigurationSection method. The "gets" and "sets" are not particulary attractive, nor is the fact that we have to name each attribute using the same string twice. e.g. constant string "Login" is specified twice, a recipe for disaster if you missspelll it.
This time we scope the settings to the user, not to the application, as login information typically belongs to the user.
The save and load methods are as follows. These are much cleaner than before.
private void LoadAllSettings()
{
// MainFormSettings.Reload();
edURL.Text = MainFormSettings.ServerURL;
edAlias.Text = MainFormSettings.Alias;
edLogin.Text = MainFormSettings.Login;
edPwd.Text = "";
}
private void SaveAllSettings()
{
MainFormSettings.ServerURL = edURL.Text;
MainFormSettings.Alias = edAlias.Text;
MainFormSettings.Login = edLogin.Text;
MainFormSettings.Save();
}
We can take this as our final solution unless someone has a way to make ApplicationSettingsBase a little less ugly.
max265
User-scope settings can be changed and saved at run time, but application-scope settings are read-only and cannot be changed programmatically. Changing user-scope settings in VB is quite trivial ==>
My.Settings.Nickname = newNickname
Refer to this article for more details ==> http://msdn2.microsoft.com/en-us/library/shytyc55.aspx
ibrahimkurt
From the documentation on the ConfigurationManager class:
Read a section from a configuration file. To access configuration information, use GetSection For some sections such as appSettings and connectionStrings, use the AppSettings and ConnectionStrings classes. The methods mentioned above perform read-only operations, use a single cached instance of the configuration, and are multithread aware.
So that was my mistake. AppSettings is read-only.
Here is my new question. How can I write a string value by name, to the configuration file, in one or two lines of code