I created an App.config file in my WPF application:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appsettings>
<add key="xmlDataDirectory" value="c:\testdata"/>
</appsettings>
</configuration>
Then I try to read the value out with this:
string xmlDataDirectory = ConfigurationSettings.AppSettings.Get("xmlDataDirectory");
But it says this is obsolete and that I should use ConfigurationManager which I can't find, even searching in the class view.
Does anyone know how to use config files like this in WPF?
You have to reference the System.Configuration assembly which is in GAC.
Use of ConfigurationManager is not WPF-specific: it is the privileged way to access configuration information for any type of application.
Please see Microsoft Docs - ConfigurationManager Class for further info.
In my case, I followed the steps below.
App.config
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="POCPublishSubscribeQueueName" value="FormatName:Direct=OS:localhost\Private$\POCPublishSubscribe"/>
</appSettings>
</configuration>
Added System.Configuartion to my project.
Added using System.Configuration statement in file at top.
Then used this statement:
string queuePath = ConfigurationManager.AppSettings["POCPublishSubscribeQueueName"].ToString();
In your app.config, change your appsetting to:
<applicationSettings>
<WpfApplication1.Properties.Settings>
<setting name="appsetting" serializeAs="String">
<value>c:\testdata.xml</value>
</setting>
</WpfApplication1.Properties.Settings>
</applicationSettings>
Then, in the code-behind:
string xmlDataDirectory = WpfApplication1.Properties.Settings.Default.appsetting.ToString()
You have to reference System.Configuration via explorer (not only append using System.Configuration). Then you can write:
string xmlDataDirectory =
System.Configuration.ConfigurationManager.AppSettings.Get("xmlDataDirectory");
Tested with VS2010 (thanks to www.developpez.net).
Hope this helps.
You have to add the reference to System.configuration in your solution. Also, include using System.Configuration;. Once you do that, you'll have access to all the configuration settings.
This also works
WpfApplication1.Properties.Settings.Default["appsetting"].ToString()
You can change configuration file schema back to DotNetConfig.xsd via properties of the app.config file. To find destination of needed schema, you can search it by name or create a WinForms application, add to project the configuration file and in it's properties, you'll find full path to file.
There is a good article about Application settings on Microsoft.
According to that you need to:
manually create App.config file (from Project Context menu -> Add -> New Item... -> Application Configuration File.)
add required sections there (I'm using only application scope settings):
<?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="DevelopmentEnvironmentManager.WPF.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</sectionGroup>
</configSections>
<applicationSettings>
<DevelopmentEnvironmentManager.WPF.Properties.Settings>
<setting name="SqliteDbFilePath" serializeAs="String">
<value>Database.db</value>
</setting>
<setting name="BackgroundColor" serializeAs="String">
<value>White</value>
</setting>
<setting name="TextColor" serializeAs="String">
<value>Black</value>
</setting>
</DevelopmentEnvironmentManager.WPF.Properties.Settings>
</applicationSettings>
</configuration>
NOTE: Replace 'DevelopmentEnvironmentManager.WPF' with the name of your application.
Additionally, you can go to Properies of the project and add Settings.Designer:
this will add convenient designer to your project, so you don't have to edit XML manually:
To access settings from the code - simply save and close all config editors, build app and access static Propeties (again, do not forget to change app name in the namespace):
string databasePath = DevelopmentEnvironmentManager.WPF.Properties.Settings.Default.SqliteDbFilePath;
I have a Class Library WPF Project, and I Use:
'Read Settings
Dim value as string = My.Settings.my_key
value = "new value"
'Write Settings
My.Settings.my_key = value
My.Settings.Save()
Related
I would like to access the values in the ConfigurationManager.AppSettings object from a MEF plugin which has its own app.config file.
However, the keys from the app.config file are not present in AppSettings after the plugin is loaded.
The keys from the application loading the plugin are still present.
I noticed that using a Settings.settings file allows this behaviour, via the app.config file, so the file must be being loaded somehow.
My plugin looks like:
[Export(IPlugin)]
public class Plugin
{
public Plugin()
{
// reads successfully from app.config via Settings object
var value1 = Settings.Default["Key1"];
// returns null from app.config via ConfigurationManager
var value1 = ConfigurationManager.AppSettings["Key2"]
}
}
The app.config looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="..." >
<section name="Plugin.Settings" type="..." />
</sectionGroup>
</configSections>
<appSettings>
<add key="Key2" value="Fails" />
</appSettings>
<applicationSettings>
<Plugin.Settings>
<setting name="Key1" serializeAs="String">
<value>Works</value>
</setting>
</Plugin.Settings>
</applicationSettings>
</configuration>
I can manually load the app.config file with:
var config = ConfigurationManager.OpenExeConfiguration("Plugin.dll");
var value = AppSettings.Settings["Key2"].Value
but this seems more like a workaround than a solution.
Is there a way to access a MEF plugin's <appSettings> directly, from inside the plugin?
If not, what is recommended?
By default the ConfigurationManager loads the .config for the entry assembly, i.e. the assembly that started the currently executing process.
The correct way to do this would be something like this:
[Export(IPlugin)]
public class Plugin
{
public Plugin()
{
var config = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
var value = config.AppSettings.Settings["Key2"].Value;
}
}
This would make the plugin automatically open the .config for the DLL it was compiled in, and fetch values from there.
I'd recommend you to use a dependency injection tool like Unity, in order to provide to your plug-ins the configuration they required. By proceeding in this way, your plug-ins will no longer need to reference System.Configuration.dll.
When are settings from app.config actually read by application?
Suppose I have a windows service and some app settings for it. In code I have a method where some setting is used. Method is being called in every iteration, not just once during all the time. If I change the setting value through the configuration file should I restart the service for it to be "refreshed" inside or will it be accepted the next time without any interaction from my side?
You need to call ConfigurationManager.RefreshSection method to get the latest values read directly from disk. Here's a simple way to test and provide answer to your question:
static void Main(string[] args)
{
while (true)
{
// There is no need to restart you application to get latest values.
// Calling this method forces the reading of the setting directly from the config.
ConfigurationManager.RefreshSection("appSettings");
Console.WriteLine(ConfigurationManager.AppSettings["myKey"]);
// Or if you're using the Settings class.
Properties.Settings.Default.Reload();
Console.WriteLine(Properties.Settings.Default.MyTestSetting);
// Sleep to have time to change the setting and verify.
Thread.Sleep(10000);
}
}
My app.config containing:
<?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="ConsoleApplication2.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<appSettings>
<add key="myKey" value="Original Value"/>
</appSettings>
<userSettings>
<ConsoleApplication2.Properties.Settings>
<setting name="MyTestSetting" serializeAs="String">
<value>Original Value</value>
</setting>
</ConsoleApplication2.Properties.Settings>
</userSettings>
</configuration>
After you start the application, open the app.config within the build folder, and change the value of the appSetting "myKey". You'll see the new value printed out to the console.
To answer the question, yes they are cached on the first time they are each read I think, and to force the read straight from the disk, you need to refresh the section.
Either when you load it up via the configuration manager (ConfigurationManager.GetSection("x/y");) or when you try to access the properties.
There is a slight grey area here because when you get the configuration out via the config manager:
var config = (MyConfigSection)ConfigurationManager.GetSection("MyConfigSection");
You get a configuration object back if you have provided the configuration section type in the configurationSections element at the top of the config file. If you do not actually provide the actual config you will still get an object back.
However if you have a required field that is not set it will not throw an exception till you call the property. I have worked this out whilst trying to unit test my custom configuration sections.
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);
I am trying to get the value for the key "sUser" in appSetting section from app.config
this is the code on my class.cs
string sUsr = ConfigurationManager.AppSettings.Get["sUser"];
But always its null.
I try this code (I took it from MSDN):
// Get the configuration file.
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get the appSettings section.
AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("appSettings");
// Get the auxiliary file name.
Console.WriteLine("Auxiliary file: {0}", config.AppSettings.File);
But it shows that the file Empty
Also I am using the stting console to write those properties and it works if I get the apps using
string sUsr = WIW.Business.Properties.Settings.Default.sUser;
But I am going to use that class as a reference in a website and on the web.config of the site I can't configure those settings
In your App.config the appSettings section should look like the following:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="sUser" value="Test"/>
</appSettings>
</configuration>
use Properties.Settings.Default.{your_setting_key} to access the value
I.E
Properties.Settings.Default.sPassword return 8909039388
All these were included in Properties Class.
I had the same problem. I was calling another project(In the same solution) and was expecting the appSettings to be present.
To make it work,I added the following lines in the application that was calling the target application.
<appSettings>
<add key="sUser" value="Test"/>
</appSettings>
It worked for me after that. Try this. It might help you too
Here its my app.config, if I try to get the key values from the appSettings sections I always get null, but If I try to get them from applicationsection Its no problem, the thing is that I need put that applicationsection on a web site but on a web site i can put applicationSettings
<configuration>
<appSettings>
<add key="sUser" value="userbancolombia">
<add key="sPassword" value="8909039388">
<appSettings>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="WIW.Business.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<system.serviceModel>
<bindings />
<client />
</system.serviceModel>
<applicationSettings>
<WIW.Business.Properties.Settings>
<setting name="WIW_Business_WsCCMain_ConsultaNuips" serializeAs="String">
<value>http://coomeva1/AsisaWS_2008/ConsultaNuips.asmx</value>
</setting>
<setting name="WIW_Business_WsCCAux_ConsultaNuips" serializeAs="String">
<value>http://coomeva1/AsisaWS_2008_Sec/ConsultaNuips.asmx</value>
</setting>
<setting name="WIW_Business_WsCEMain_ConsultaCedulaExtranjeria"
serializeAs="String">
<value>http://coomeva1/AsisaWS_2008/ConsultaCedulaExtranjeria.asmx</value>
</setting>
<setting name="WIW_Business_WsCEAux_ConsultaCedulaExtranjeria"
serializeAs="String">
<value>http://coomeva1/AsisaWS_2008_Sec/ConsultaCedulaExtranjeria.asmx</value>
</setting>
<setting name="sUser" serializeAs="String">
<value>userbancolombia</value>
</setting>
<setting name="sPassword" serializeAs="String">
<value>8909039388</value>
</setting>
</WIW.Business.Properties.Settings>
</applicationSettings>
</configuration>
I've tried updating my application's .config file during installer (via a .NET Installer Class Action). But, I can't seem to get ConfigurationManager to list any properties or be able to set anything.
I learned of this approach from several stackoverflow posts that pointed me to this guide: http://raquila.com/software/configure-app-config-application-settings-during-msi-install/
I've investigated the differences between my project and his and noticed that my configuration files are formatted differently. I believe this has to do with the fact that i'm using "Settings" files.
Config files formatted in the guide look like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Param1" value="" />
<add key="Param2" value="" />
<add key="Param3" value="" />
</appSettings>
</configuration>
Where mine looks like:
<?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="MyAppName.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="MyAppName.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyAppName.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<MyAppName.Properties.Settings>
<setting name="TESTSETTING" serializeAs="String">
<value>asdfasdfasdf</value>
</setting>
</MyAppName.Properties.Settings>
<MyAppName.Settings1>
<setting name="VerboseErrorMode" serializeAs="String">
<value>False</value>
</setting>
<applicationSettings>
<MyAppName.Settings1>
<setting name="RunOnStartup" serializeAs="String">
<value>True</value>
</setting>
</MyAppName.Settings1>
</applicationSettings>
</configuration>
To shed some light on what was going on... I tried printing out the list of settings like so:
Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);
// Try getting the Settings1 Section
AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("Settings1"); // Also tried myNamespace.Settings1
if (appSettings != null)
{
valList = "Settings1: ";
foreach (string key in appSettings.Settings.AllKeys)
{
string value = appSettings.Settings[key].Value;
valList += ("Key: '" + key + "' = '" + value + "'\n");
}
}
else
{
valList = "appSettings was null";
}
MessageBox.Show(valList);
MessageBox.Show(valList);
I have tried several permutations of this... and in all cases output is "appSettings was null".
I also tried initializing the configuration manager in several different ways...
Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);
MessageBox.Show("Section Count: " + config.Sections.Count);
MessageBox.Show("Has File: " + config.HasFile);
MessageBox.Show("Namespace Declared: " + config.NamespaceDeclared);
config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
MessageBox.Show("Section Count: " + config.Sections.Count);
MessageBox.Show("Has File: " + config.HasFile);
MessageBox.Show("Namespace Declared: " + config.NamespaceDeclared);
For each of them the section count returned was 20. (I have no idea where the 20 comes from... I would have expected it to be 3).
HasFile was true for the first case and false for the second.
Namespace Declared was false in both cases.
Thanks!
EDIT (6-18-09): Still looking into this question. Anyone else have any ideas? Thanks.
Search Keywords: "Object Reference Not Set to not set to an instance" <-- this occurs when trying to write to a property.
I came across the same problem, after deep investigation, I found out the easiest way to update any part of config files (e.g. app.config), that's by using XPath.
We have an application which connects to web service, during the installation, the user enters the URL of the web service and this should be saved in the following app.config file:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="ApplicationServer.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<ApplicationServer.Properties.Settings>
<setting name="ApplicationServer_ApplicationServerUrl" serializeAs="String">
<value>whatever comes from setup should go here</value>
</setting>
</ApplicationServer.Properties.Settings>
</applicationSettings>
</configuration>
Here is the code to do this in the installer class:
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
string targetDirectory = Context.Parameters["targetdir"];
string param1 = Context.Parameters["param1"];
string path = System.IO.Path.Combine(targetDirectory, "app.config");
System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
xDoc.Load(path);
System.Xml.XmlNode node = xDoc.SelectSingleNode("/configuration/applicationSettings/Intellisense.ApplicationServer.Properties.Settings/setting[#name='ApplicationServer_ApplicationServerUrl']/value");
node.InnerText = (param1.EndsWith("/") ? param1 : param1 + "/");
xDoc.Save(path); // saves the web.config file
}
Basically, since the config file is a XML based document, I am using XPath expression to locate specific node and change its value.
One thing to try is moving it from install to Commit to ensure that the file has been written first before trying to access it. Alternatively you could use the custom action to write your own file and just alter your config file to point at the alternative xml file.
I worked on a Sharepoint product install where I dug into all of this and I will admit it is very tedious to get working correctly. I was creating config and batch files on the fly based on install parameters.
You can access these settings using the System.Configuration namespace but, its not as simple as I would like and in retrospect using System.Xml.Linq is far simpler. Anyway, here is how I got it to work.
The important concept is, the applicationSettings section is not AppSettings, its a seperate section supported by the ClientSettingsSection type.
//Open the application level config file
ExeConfigurationFileMap exeMap = new ExeConfigurationFileMap();
exeMap.ExeConfigFilename = String.Format("{0}.config",
Context.Parameters["assemblypath"]);
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(exeMap,
ConfigurationUserLevel.None);
//Get the settings section
ClientSettingsSection settingsSection =
config.GetSectionGroup("applicationSettings").Sections
.OfType<ClientSettingsSection>().Single();
//Update "TheSetting"
//I couldn't get the changes to persist unless
//I removed then readded the element.
SettingElement oldElement = settingsSection.Get("TheSetting");
settingsSection.Settings.Remove(oldElement);
SettingElement newElement = new SettingElement("TheSetting",
SettingSerializeAs.String);
newElement.Value = new SettingValueElement();
newElement.Value.ValueXml = oldElement.Value.ValueXml.CloneNode(true);
newElement.Value.ValueXml.InnerText = "Some New Value";
settingsSection.Add(newElement);
//Save the changes
config.Save(ConfigurationSaveMode.Full);
So, as you can see, simple. :-S
Instead of accessing your settings configuration via ConfigurationManager, you should be able to access it via Settings.Default. Settings are more of a Visual Studio feature than a .NET feature...a convenience that makes it easy to visually design your applications configuration rather than manually writing it in appSettings or creating custom configuration sections. However, the configuration schema that is rendered when you use Settings is non-standard, and can be difficult to access manually.
Visual Studio should have generated a Settings class for you when you built your application, and you should be able to access that class via Properties.Settings.Default. It should have a property for each setting, in your case, the following:
Properties.Settings.Default.TESTSETTING
Properties.Settings.Default.VerboseErrorMode
Properties.Settings.Default.RunOnStartup
You should be able to both read and write these settings. A critical thing to note...anything flagged as a "user" setting will not be written back to the {yourapplication}.exe.config file...it will be written to a User.config file in the users isolated profile storage area. This is under C:\Documents and Settings{username} on XP, and C:\Users{username} on Vista, in the AppData folder. Depending on the OS and users profile, the subfolder under the AppData may change, but its completely unique and keyed to a particular version of the application. Installation of a newer version will result in a completely new set of configuration settings stored under the same keyed folder, but a different version subfolder.
I hope this helps. :)
This is what you need: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/f89a00eb-9400-48ce-af20-cef78002c14e