Update config file after value change - c#

I am updating one setting in my config file on button click. The code i found is easy to understand and I am sure it works that way. But the problem lies with either updating the section in my config file or writing to it.
So on button click it goes through this method:
private static void UpdateSetting(string key, string value)
{
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
configuration.AppSettings.Settings[key].Value = value;
configuration.Save();
ConfigurationManager.RefreshSection("applicationSettings");
}
And this is the targetet section in my config file:
<applicationSettings>
<UpdatePackager.Properties.Settings>
<setting name="Sourcepath" serializeAs="String">
<value>D:\PMSmart</value>
</setting>
<setting name="DestinationpathUpdatePackages" serializeAs="String">
<value>D:\xxx</value>
</setting>
<setting name="DestinationpathClient" serializeAs="String">
<value>D:\xxx</value>
</setting>
<setting name="Versions" serializeAs="String">
<value>v5_9_0/v5_9_1/v5_9_2</value>
</setting>
</UpdatePackager.Properties.Settings>
</applicationSettings>
Am i missing something or doing something the wrong way?

It is the .config file in the output directory of your .exe that should get updated, and not the one in your project folder.
When you build the application and run it again, the modified config file will be overwritten by the one in your project folder.
Check the value in the .config file in the bin/Debug or bin/Release folder during runtime and you should see that it has been updated after your UpdateSetting method has been executed.

Related

How to properly use Properties.Settings.Default.Save()?

I'm writing an application with Windows Forms, .NET 4.6, using a bunch of settings configurable in run-time. Modifying, adding and deleting settings works fine within one run, but all changes are lost when the app closes. I do use Properties.Settings.Default.Save() just before the main window closes:
private void TestersList_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings.Default.Save();
}
A user.config file is created as expected in AppData, but only one of the settings is saved there, no matter what I do with it or any other setting in run time.
All of the settings are defined in user scope and serialized as strings. I see nothing that makes the one that is saved any different from the others.
Below is a part of app.config:
<userSettings>
<DailyChecklist.Properties.Settings>
<setting name="SerialPattern2" serializeAs="String">
<value>\d{10}_0_None</value>
</setting>
</setting>
<setting name="SerialPatternDebug" serializeAs="String">
<value>123456789</value>
</setting>
<setting name="TestersToIgnore" serializeAs="String">
<value>dummy;</value>
</setting>
<setting name="SerialPatternDefault" serializeAs="String">
<value>\D\d]{3}\D{2,3}\d{4}\d{5}</value>
</setting>
<setting name="ServerAdress" serializeAs="String">
<value>address/goes/here</value>
</setting>
</DailyChecklist.Properties.Settings>
</userSettings>
And after saving I got this in user.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<DailyChecklist.Properties.Settings>
<setting name="TestersToIgnore" serializeAs="String">
<value>dummy;</value>
</setting>
</DailyChecklist.Properties.Settings>
</userSettings>
</configuration>
How can I make it save all settings in user.config?
Thanks in advance!
PS. I have checked that it's not the scope, I have no '*' in assembly info and the file I was monitoring is the only file created (no version/build number changes). It gets modified (according to notepad++) and if I change TestersToIgnore, its new value is saved, but all other settings are missing.
Well, I figured it out finally, so I'm leaving it here for future unfortunate souls.
The magical word is: foreach.
Although it is possible to iterate through Properties.Settings.Default.Properties in a foreach loop, changes are temporary. I mean solution like:
foreach(SettingsProperty setting in Properties.Settings.Default.Properties)
{
if(setting.Name.Contains("someKeyWord"))
Properties.Settings.Default[setting.Name] = someNewSettingValue;
}
seems to be working within current run, but changes are lost after restart. Properties.Settings.Default.Save() for some reason won't save anything that was changed from within a loop.
I checked and Properties.Settings.Default[setting.Name] = someNewSettingValue; works just fine outside of a loop and is normally saved then.
If you need dynamically added settings, consider using a single setting configured as one of System.Collections.Specialized types. It might make your code less transparent, but at least it handles loops well.

Application settings reset when exe changes location [duplicate]

This question already has answers here:
Settings.settings File Keeps Getting Reset
(4 answers)
Closed 6 years ago.
Hi I'm using the Visual Studio config files, however the settings change every time I move the exe.
How can I fix this?
app.config
<?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="GUIChangerUI.Properties.Settings" 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.2" />
</startup>
<userSettings>
<GUIChangerUI.Properties.Settings>
<setting name="StarmadePath" serializeAs="String">
<value>default</value>
</setting>
<setting name="GuiPath" serializeAs="String">
<value>Not selected yet.</value>
</setting>
<setting name="FirstStart" serializeAs="String">
<value>True</value>
</setting>
<setting name="jpeg" serializeAs="String">
<value>default</value>
</setting>
<setting name="debug" serializeAs="String">
<value>default</value>
</setting>
<setting name="Darktheme" serializeAs="String">
<value>False</value>
</setting>
<setting name="Lightheme" serializeAs="String">
<value>True</value>
</setting>
<setting name="starmadeStarter" serializeAs="String">
<value />
</setting>
<setting name="_starmadeStarter" serializeAs="String">
<value />
</setting>
<setting name="OSMTheme" serializeAs="String">
<value>False</value>
</setting>
</GUIChangerUI.Properties.Settings>
</userSettings>
</configuration>
The actual configuration file containing saved configuration settings is stored here:
%APPDATA%\Local\<application name>\<application name>.<eid>_<hash>\<version>
According to this MSDN article::
<eid> is the URL, StrongName, or Path, based on the evidence available to hash.
<hash> is a SHA1 hash of evidence gathered from the CurrentDomain, in the following order of preference:
StrongName
URL
If neither of these is available, use the .exe path.
(my emphasis)
So the solution seems simple:
Create a strong name and sign your executable.
Then you will get the same unique hash every time and it won't change whenever you start the executable from a new location.
If you need help signing your application, please refer to this MSDN article: How to: Sign an Assembly with a Strong Name.
The user settings will be stored in your user's profile in such a way that the location of your application is linked. That's why the application, when moved, does not find the settings anymore.
What you can try to do is:
Create a new user setting named SettingsUpgradeRequired and set it to true in the settings designer in Visual Studio.
In your application's startup code, check whether SettingsUpgradeRequired is true and if so, perform a settings upgrade.
As the new setting will only be true after the settings file was reset, the following should import the old settings, and it should do so only once:
if (Properties.Settings.Default.SettingsUpgradeRequired)
{
try
{
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.SettingsUpgradeRequired = false;
Properties.Settings.Default.Save();
}
catch (...)
{
... // Upgrade failed - tell the user or whatever
}
}
That behavior is by design because you could have multiple versions of you application (for instance a QA version, a PROD version and so on) that requires different setting storages. See also Client Settings FAQ for details.
If you need a settings management that is independend of the location / version of you app, i would suggest wo create your own settings file and store them below "%appdata%[company][application]"

Save and reload app.config(applicationSettings) at runtime

I've stored configuration of my application in the app.config, by Visual Studio I've created some application key on the settings tab of project properties dialog, then I've set this key at application level(NOT at user level).
Visual Studio automatically generate the following xml file (app.config) :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="AleTest.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<AleTest.Properties.Settings>
<setting name="DatabasePath" serializeAs="String">
<value>Test.s3db</value>
</setting>
<setting name="DatabaseUser" serializeAs="String">
<value />
</setting>
<setting name="DatabasePass" serializeAs="String">
<value />
</setting>
</AleTest.Properties.Settings>
</applicationSettings>
</configuration>
Now I want to save and reload the settings at runtime, here's my code that allow to save the value DatabasePath in the configuration file:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSectionGroup applicationSectionGroup = config.GetSectionGroup("applicationSettings");
ConfigurationSection applicationConfigSection = applicationSectionGroup.Sections["AleTest.Properties.Settings"];
ClientSettingsSection clientSection = (ClientSettingsSection)applicationConfigSection;
//Database Configuration Setting
SettingElement applicationSetting = clientSection.Settings.Get("DatabasePath");
applicationSetting.Value.ValueXml.InnerXml = this.textBoxPath.Text.Trim();
applicationConfigSection.SectionInformation.ForceSave = true;
config.Save();
The problem is that with this code the new settings aren't loaded by application until I restart the application; is there a way to reload the config settings at runtime?
I also want to replace the fixed value of the name of applicationSettings section (AleTest.Properties.Settings) with a variable value, exist a variable in the framework the assume this value (AleTest.Properties.Settings) ?
You need to make a call to ConfigurationManager.RefreshSection in order to have the values re-read from disk.
I did a some tests and here is result.
For auto generated class Settings the call of ConfigurationManager.RefreshSection("applicationSettings"); doesn't apply the modified values for members marked with ApplicationScopedSettingAttribute, it applies the changes to future calls via ConfigurationManager members (and not sure about UserScopedSettingAttribute).
Instead call Settings.Default.Reload();
What you want is accomplish able by creating an custom ConfigSection which allows you more control and allows you to change the name. Configuration manager has a refresh section which will allow you reload the data.
Aleroot's code for updating values worked fine.
In spite of Properties.Settings being write only (no set).
To refresh, this worked for me:
ConfigurationManager.RefreshSection("applicationSettings");
But I'm using this to access the parameter:
string test = Properties.Settings.Default.MyString;
MessageBox.Show("Paramètres/Settings MyString = " + test);

C# - Compiler Error: System.Configuration.ConfigurationErrorsException was unhandled

Hey Everyone,
How do I fix the Compiler Error upon compiling on "return ((string)(this["TargetDir"]));":
System.Configuration.ConfigurationErrorsException was unhandled
Configuration system failed to initialize
{"Unrecognized configuration section userSettings/CCP.Settings1. (C:\\Users\\bmccarthy\\Documents\\Visual Studio 2008\\Projects\\CCP Utility\\CCP Utility\\bin\\Debug\\CCP_Utility.exe.config line 21)"}
A first chance exception of type 'System.Configuration.ConfigurationErrorsException' occurred in System.Configuration.dll
Here's the code in my Settings.Designer.cs file under the Properties directory:
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string TargetDir {
get {
return ((string)(this["TargetDir"]));
}
set {
this["TargetDir"] = value;
}
}
Here's the code for CCP_Utility.exe.config from the bin folder:
<CCP_Utility.Properties.Settings>
<setting name="SourceDir" serializeAs="String">
<value />
</setting>
<setting name="TargetDir" serializeAs="String">
<value />
</setting>
<setting name="CorpID" serializeAs="String">
<value />
</setting>
</CCP_Utility.Properties.Settings>
<CCP_Utility.Settings1>
<setting name="sourceDir" serializeAs="String">
<value />
</setting>
<setting name="targetDir" serializeAs="String">
<value />
</setting>
</CCP_Utility.Settings1>
What does the < CCP_Utility.Settings1 > tag have to match up to?? App.config and what else?
Does capitalization matter? I have the variable declared as TargetDir Settings.Settings....
Where is the System.Configuration.dll file located?
I got the application to compile without compiler errors by changing the capitilzation of sourceDir and targetDir under CCP_Utility.Settings1 in the Settings1.Designer.cs file as follows:
<CCP_Utility.Settings1>
<setting name="SourceDir" serializeAs="String">
<value />
</setting>
<setting name="TargetDir" serializeAs="String">
<value />
</setting>
</CCP_Utility.Settings1>
Verify UserScopedSettingAttribute matches up with the correct settings section.
If I remember correct, yes, case-sensitive.
Usually, I will add a setting, save and close, then open the settings designer again, and delete the setting, save and close. This will get the designer in-sync. I have seen them get out-of-sync the first time the designer is opened on a computer. (For example, when you get from source control.)

web.release.config change dynamic webservice url

I'm editing my web.release.config file for production. I want the web.config file changed after a publish.
I found how to change the web.config by using the web.release.config file properly, but not for this particular component.
The URL of an dynamic webservice has to change.
In the web.config:
<applicationSettings>
<FooService.Properties.Settings>
<setting name="FooService_Student" serializeAs="String">
<value>http://testwebservices.foo.bar.nl/Student.asmx</value>
</setting>
<setting name="FooService_User" serializeAs="String">
<value>http://testwebservices.foo.bar.nl/User.asmx</value>
</setting>
</FooService.Properties.Settings>
</applicationSettings>
now, how do I change the <value> in both settings? I tried the following, but that didn't work out:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<applicationSettings>
<FooService.Properties.Settings>
<setting name="FooService_Student" serializeAs="String" xdt:Transform="Replace">
<value>http://webservices.foo.bar.nl/Student.asmx</value>
</setting>
<setting name="FooService_User" serializeAs="String" xdt:Transform="Replace">
<value>http://webservices.foo.bar.nl/User.asmx</value>
</setting>
</FooService.Properties.Settings>
</applicationSettings>
</configuration>
Anyone experience with this matter?
Thankyou!
Add xdt:Transform="Replace" to the applicationSettings tag.
<applicationSettings xdt:Transform="Replace">
<FooService.Properties.Settings>
<setting name="FooService_Student" serializeAs="String">
<value>http://webservices.foo.bar.nl/Student.asmx</value>
</setting>
<setting name="FooService_User" serializeAs="String">
<value>http://webservices.foo.bar.nl/User.asmx</value>
</setting>
</FooService.Properties.Settings>
How about adding a xdt:Locator="Match(name)", that will probably be what you need to find the exact nodes to replace.

Categories