ConfigurationManager class. ConfigurationSection properties cannot be edited when locked - c#

Here is code:
// These is works
Console.WriteLine(Properties.Settings.Default.name);
Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
KeyValueConfigurationCollection settings = configFile.AppSettings.Settings;
settings.Add("Port", "12");
// Here it fails
configFile.Save(ConfigurationSaveMode.Modified);
Content of app.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="ConsoleApplication1.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
</sectionGroup>
</configSections>
<userSettings>
<ConsoleApplication1.Properties.Settings>
<setting name="name" serializeAs="String">
<value>dasdqweqw</value>
</setting>
</ConsoleApplication1.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/></startup></configuration>
Can not understand why it is not working. Code is right or I am doing something wrong? On the line configFile.Save(ConfigurationSaveMode.Modified); it throws an exception "ConfigurationSection properties cannot be edited when locked."
What scenario I have decided to follow:
1. Via Solution explorer I am opening project properties page (Solution explorer > context menu of project node > Properties), then via Settings tab in project properties page I am creating project's application settings (value of Scope parameter is User). This creates Properties class (located in Settings.Designer.cs file) in namespace of the project & corresponding class properties. https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2008/cftf714c%28v=vs.90%29
2. To create user specific user.config file I have to change added settings & call Properties.Settings.Default.Save() method. If I just call Properties.Settings.Default.Save() without changing settings first this does not create user.config file.
Usage exmple:
Properties.Settings.Default.updateTime = DateTime.UtcNow;
Properties.Settings.Default.Save();
Console.WriteLine((Properties.Settings.Default.updateTime - DateTime.UtcNow).Hours);
Console.ReadLine();
Content of user.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<coonfoo.Properties.Settings>
<setting name="updateTime" serializeAs="String">
<value>06/03/2018 10:42:03</value>
</setting>
</coonfoo.Properties.Settings>
</userSettings>
</configuration>

This should work.
class Program
{
static void Main(string[] args)
{
Configuration roaming = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = roaming.FilePath;
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
KeyValueConfigurationCollection settings = configuration.AppSettings.Settings;
settings.Add("Port", "12");
configuration.Save(ConfigurationSaveMode.Modified);
}
}
Found this which might help you.

Related

Read settings added manually to app.config after compile

I developed a Windows service. It uses a MyService.exe.config file for configuration, that looks like this (simplified with just one setting, Prop1):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyNamespace.MyService.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<MyNamespace.MyService.Properties.Settings>
<setting name="Prop1" serializeAs="String">
<value>Foo</value>
</setting>
</MyNamespace.MyService.Properties.Settings>
</applicationSettings>
</configuration>
When I deploy to a customer production environment I need to add more settings manually on the config file, for instance Prop2:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyNamespace.MyService.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<MyNamespace.MyService.Properties.Settings>
<setting name="Prop1" serializeAs="String">
<value>Foo</value>
</setting>
<setting name="Prop2" serializeAs="String">
<value>Bar</value>
</setting>
</MyNamespace.MyService.Properties.Settings>
</applicationSettings>
</configuration>
Now if I start the service this lines of code:
log.Debug(Properties.Settings.Default["Prop1"].ToString());
log.Debug(Properties.Settings.Default["Prop2"].ToString());
produce following output:
Foo
Impossibile trovare la proprietà di impostazione 'Prop2'.
in System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
in System.Configuration.SettingsBase.get_Item(String propertyName)
in System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
in System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
in ...
The error in Italian means "Cannot find settings property 'Prop2'".
How can I read settings added to app.config after compile time?
I'm wondering whether it is not possible to add new settings to app.config when the application is already deployed, because every setting must be compiled and made available statically in Properties.Settings.Default. So to achieve what I want should I use a settings file managed by me, like re-inventing the wheel?
Well, I had posted an idea I thought would work but went back and tested myself and it didn't. D***.
So here's a suggestion I do use when the regular Settings stuff doesn't work.
Create an XML file structured as DataSet (the easiest way to do this is write a short program that creates a DatSet, populates it, and saves it as XML.
DataSet mydataset = new DataSet("myDataSet");
DataTable mydatatable = new DataTable("myDataTable");
mydatatable.Columns.Add(new DataColumn("myColumn1"));
DataRow newrow = mydatatable.NewRow();
newrow["myColumn1"] = "somedata";
mydatatable.Rows.Add(newrow);
mydataset.Tables.Add(mydatatable);
mydataset.WriteXML(#"C:\mydataset.xml", XmlWriteMode.WriteSchema);
This creates your basic XML file.
Very Important!!!!! To serialize a DataSet and/or DataTable you MUST give them names when you create them:
new DataSet("mydataset")
Then, as long as you don't violate the integrity of the XML structure, you can add rows (and even columns) to you XML file any time you wish using your favorite text editor.
In your application you simply read the XML file back into a DataSet and iterate through your DataTable rows (and through each DataTable if you created more than one) and process accordingly.
DataSet myDataSet = new DataSet("mydataset");
myDataSet.ReadXml(#"C:\mydataset.xml")
foreach (DataTable t in myDataSet.Tables)
{
foreach (DataRow r in t.Rows)
{
//process here
}
}
Very Important!!!!! To process the data you MUST use the names for the DataSet and DataTable from the XML file.
Hope this helps. It has worked for me many times when I couldn't use or couldn't access the built-in settings handler. It does add a little bit more time to your coding but....
John

How to update setting in app.config.exe file runtime

I am trying to update value of a particular setting in app.config.exe at run time. But as per my code its getting updating in vshost32.exe file which seem to duplicate as app.config.exe. My code is given below
private void btnSubmit_Click(object sender, EventArgs e)
{
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSectionGroup applicationSectionGroup = config.GetSectionGroup("applicationSettings");
string d = applicationSectionGroup.Sections[0].ToString(); ;
ConfigurationSection applicationConfigSection = applicationSectionGroup.Sections["Secure_Browser_CS_Version.Properties.Settings"];
ClientSettingsSection clientSection = (ClientSettingsSection)applicationConfigSection;
//Encryption Key Configuration Setting
SettingElement applicationSetting = clientSection.Settings.Get("NavigateURL");
applicationSetting.Value.ValueXml.InnerXml = txtURL.Text;
applicationConfigSection.SectionInformation.ForceSave = true;
config.Save();
}
// app.config.exe
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyApplicationName.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<MyApplicationName.Properties.Settings>
<setting name="NavigateURL" serializeAs="String">
<value></value>
</setting>
</MyApplicationName.Properties.Settings>
</applicationSettings>
</configuration>
It seems you are doing everything correct, but since you are running using vshost.exe, this is the exe whose configuration is updated.
To run without vshost, uncheck the "Enable the Visual Studio hosting process" checkbox in Project prroperties -> Debug tab:

Storing settings in configFile

Try to save all data in to config file, and then read it and apply to my program during running - as user preference.
Whats done: create new config file (using Add new element-> add congif file). In this file put simple code
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSetting>
<add Key="Volume" value="100" />
</appSetting>
</configuration>
After it create method
public int GetVolumeFromConfigFile()
{
return Convert.ToInt32(ConfigurationManager.AppSettings.Get("Volume"));
}
and in main programm call it like
Value = (MyClass.GetVolumeFromConfigFile());
But it's not work. (During debaggin it's return nothing)
Think it can be few reason:
I need to add (I don't now in what way) what config file to use, because i have few files *.config - one as default (App.exe.config, and another - that i created)
I use incorrect method to get value from config file
Also I read about some another way to store app settings, like store it in *.settings file
What I'm doing wrong and what method prefered?
Additional information - use net 4.0
EDIT
Remove my config file, and add to existed few lines (in strong>)
<?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="PlayDemo.SettingsPlayIt" 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" />
</startup>
<userSettings>
<PlayDemo.SettingsPlayIt>
<setting name="Volume" serializeAs="String">
<value>10</value>
</setting>
</PlayDemo.SettingsPlayIt>
</userSettings>
Here I add my key
<appSetting>
<add key="Volume" value="100" />
</appSetting>
</configuration>
try this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Volume" value="100" />
</appSettings>
</configuration>
and
return Convert.ToInt32(ConfigurationManager.AppSettings["Volume"]);
the appSettings are key value pairs, so you can access it like you would a value in a Dictionary
If you want to use a separate config file, try this:
Dim config As System.Configuration.Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
config.AppSettings.File = "yourFileName"'tell Configuration what file to read
config.Save(ConfigurationSaveMode.Modified) ' save the Configuration setting
ConfigurationManager.RefreshSection("appSettings") ' update just the <appSettings> node
I really like the following technique, using ConfigurationSection. This allows you for painless manipulation of your configuration. But it is more specific upfront.
http://msdn.microsoft.com/en-us/library/2tw134k3%28v=vs.90%29.aspx

C#: Read and modify settings in another application's app.config file

I have a number of applications running which communicate with each other but none of these applications have their own user interface. I have a system console application which acts as a user interface for the system (i.e. the set of applications which all talk to each other).
I would like to be able to use the system console to read and modify the configuration of each of the non-gui apps.
Each app has an app.config file created using the Visual Studio Settings GUI. The settings are all in application scope, which results in an app.config file which looks a bit like this:
<?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="ExternalConfigReceiver.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<ExternalConfigReceiver.Properties.Settings>
<setting name="Conf1" serializeAs="String">
<value>3</value>
</setting>
<setting name="Conf2" serializeAs="String">
<value>4</value>
</setting>
</ExternalConfigReceiver.Properties.Settings>
</applicationSettings>
I have tried using the following code to read the configuration settings:
System.Configuration.ExeConfigurationFileMap fileMap = new System.Configuration.ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "PATH_TO_THE_FOLDER\\app.config";
System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(fileMap, System.Configuration.ConfigurationUserLevel.None);
someVariable = config.AppSettings.Settings["Conf1"];
someVariable2 = config.AppSettings.Settings["Conf2"];
However on closer inspection of the config.AppSettings object, I find that it contains no settings.
What am I doing wrong? Am I using the wrong method to read the config file? Is this method best for a different sort of config file?
Its possible to use the config file as XML and then use XPath to change values:
using (TransactionScope transactionScope = new TransactionScope())
{
XmlDocument configFile = new XmlDocument();
configFile.Load("PathToConfigFile");
XPathNavigator fileNavigator = configFile.CreateNavigator();
// User recursive function to get to the correct node and set the value
WriteValueToConfigFile(fileNavigator, pathToValue, newValue);
configFile.Save("PathToConfigFile");
// Commit transaction
transactionScope.Complete();
}
private void WriteValueToConfigFile(XPathNavigator fileNavigator, string remainingPath, string newValue)
{
string[] splittedXPath = remainingPath.Split(new[] { '/' }, 2);
if (splittedXPath.Length == 0 || String.IsNullOrEmpty(remainingPath))
{
throw new Exception("Path incorrect.");
}
string xPathPart = splittedXPath[0];
XPathNavigator nodeNavigator = fileNavigator.SelectSingleNode(xPathPart);
if (splittedXPath.Length > 1)
{
// Recursion
WriteValueToConfigFile(nodeNavigator, splittedXPath[1], newValue);
}
else
{
nodeNavigator.SetValue(newValue ?? String.Empty);
}
}
Possible path to Conf1:
"configuration/applicationSettings/ExternalConfigReceiver.Properties.Settings/setting[name=\"Conf1\"]/value"
as far as i know you cant use the System.Configuration.Configuration to access config files of other applications
they are xml files and you can use the xml namspace to interact with them

reading content of an config file into the dll associated with it

I have saved strings in a dll application's setting. I want to retireve them.
Here is the configuration file for my dll:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxxxxxxx" >
<section name="Search.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxx" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<PishiSearch.Properties.Settings>
<setting name="ReadIndex" serializeAs="String">
<value>C:\Index</value>
</setting>
<setting name="WriteIndex" serializeAs="String">
<value>C:\WriteIndex</value>
</setting>
</PishiSearch.Properties.Settings>
</applicationSettings>
</configuration>
It resides in the same directory as my dll. It is called: Search.dll.config
My dll is called: Search.dll
I want to read the values of ReadIndex and WriteIndex from this config file into my dll.
Here is the code:
var executingAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var location = executingAssembly.Location; //C:\MyApp\bin\Debug\Search.dll
var config = ConfigurationManager.OpenExeConfiguration(location);
var sections = config.Sections; //count of this is 21
ConfigurationSectionGroup csg = config.GetSectionGroup("applicationSettings");
ConfigurationSectionCollection csc = csg.Sections;
ConfigurationSection cs = csc.Get("Search.Properties.Settings");
The code works up to getting the last line here. But how do I get the settings strings?
Yes I can use cs.SectionInformation.GetRawXml(); to get the xml and then interrogate it to get the values, but that is a kluge.
How do I read the values? Preferably into a Settings object? Many thanks!
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<applicationSettings>
</applicationSettings>
<appSettings>
<add key="ReadIndex" value="C:\Index"/>
</appSettings>
</configuration>
var executingAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var location = executingAssembly.Location; //C:\MyApp\bin\Debug\Search.dll
var config = ConfigurationManager.OpenExeConfiguration(location);
var sections = config.Sections; //count of this is 21
string s = config.AppSettings.Settings["ReadIndex"].Value.ToString();
you must add tag "appSettings" into tag "configuration" in your file "app.config" in visual studio
like the bellow:
<configuration>
<appSettings>
<add key="ReadIndex" value="aaa"/>
<add key="WriteIndex" value="111"/>
</appSettings>
</configuration>
and then use this bellow code in c#
var appConfig = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
string userName = appConfig.AppSettings.Settings["ReadIndex"].Value;
string password = appConfig.AppSettings.Settings["WriteIndex"].Value;
if you want to update your configuration you can open the "Search.dll.config" file and then update it.
please refer to the bellow answer:
Reading dll.config (not app.config!) from a plugin module

Categories

Resources