I've added a simple string-based user setting in Visual Studio 2010. When my main form loads I access this setting. This makes my application crash, throwing the following exception:
"ConfigurationErrorsException - The configuration system failed to initialize."
Is it really that hard to make use of the user settings feature? What am I missing?
PS: This is my 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="MyApp.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<MyApp.Properties.Settings>
<setting name="WorkbenchDirectory" serializeAs="String">
<value />
</setting>
</MyApp.Properties.Settings>
</userSettings>
</configuration>
The hint to look at the inner exception finally helped me to solve the problem.
The settings folder of my app (in my user's local AppData directory) was somehow corrupted.
I deleted the folder and now everything is working fine.
Thanks!
Try to give some value to your setting:
<setting name="WorkbenchDirectory" serializeAs="String">
<value>hello</value>
</setting>
Maybe an empty value node is invalid.
Related
I have a WPF application (mvvm) with multiple projects. In the main project I have an App.config file. I've added a couple of settings via Settings.settings. The App.config file looks like:
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="VSAutomation.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
<section name="log4net" type="log4net.config.Log4NetConfigurationSectionHandler, log4net" />
log4net stuff here...
<applicationSettings>
<VSAutomation.Properties.Settings>
<setting name="SimDir" serializeAs="String">
<value>"C:\Program Files (x86)\sim"</value>
</setting>
</VSAutomation.Properties.Settings>
</applicationSettings>
When I try to access these settings from one of the other modules
string appFolder = ConfigurationManager.AppSettings.Get("SimDir");
It returns null. If I set a breakpoint and evaluate
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
It points to the correct appname.exe.config file and the settings are correct.
ConfigurationManager.AppSettings.Count returns 0
This is really odd. I've looked at dozens of questions here StackOverflowflow but have not found a solution. Is it related to the log4net section?
Here is my solution, just in case anyone else has this specific version of the problem. I was trying to use the Settings.settings UI in Visual Studio. It created the structure shown above. After reviewing this article closely I tried creating an appSettings section and that worked.
<appSettings>
<add key="SimDir" value="C:\Program Files (x86)\sim"/>
</appSettings>
So now
string appFolder = ConfigurationManager.AppSettings.Get("SimDir");
retrieves the correct value.
I have configured a boolean variable in project's settings file
when I compile, in my output folder i see the variable in the .dll.config, as follows:
<setting name="ShowStats" serializeAs="String">
<value>True</value>
</setting>
In code I refer to it by Properties.Settings.Default.ShowStats
I want to be able to change my .config file and write there False or True, and to have this value reflected in runtime.
it seems that only changing it from my Settings window in Visual Studio will work in runtime.
Changing with notepad isnt working. it will always be the last value set in VS Settings window.
What am I doing wrong here?
Dlls don't actually have config files. Only the entry process has a config file. Basically: your entries need to be copied from the dll-named config file into app.config, or the exe-named config file.
Further: these values are only read at startup; if you are changing it while running, that won't do anything (unless the process chooses to restart itself by monitoring configuration - asp.net does this).
DLLs can not have config files. While they will be created by Visual Studio, they will not be read at runtime. You need to merge the DLLs configuration into the application's configuration.
The settings will keep their default values if you don't merge the configuration. I've answered how to do this here: How do I make App.config values visible for referenced ClassLibraires (Assebmlies) (It is, however, not the accepted answer in this case)
Please note: +1 for accessing settings by Settings.Default... instead of ConfigurationManager.
Example for merging the configurations taken from my answer to the question linked above: Let's assume the app.config for your DLL looks like this:
<?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="DLLSample.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
<add name="DLLSample.Properties.Settings.MyConnectionString" connectionString="Data Source=..." providerName="System.Data.SqlClient" />
</connectionStrings>
<applicationSettings>
<DLLSample.Properties.Settings>
<setting name="AllowStart" serializeAs="String">
<value>True</value>
</setting>
</DLLSample.Properties.Settings>
</applicationSettings>
</configuration>
And the app.config of your application looks like this:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="App.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<App.Properties.Settings>
<setting name="LogPath" serializeAs="String">
<value>C:\Temp</value>
</setting>
</App.Properties.Settings>
</applicationSettings>
</configuration>
After the above described changes, the application's config file should look like:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="App.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<section name="DLLSample.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
<add name="DLLSample.Properties.Settings.MyConnectionString" connectionString="Data Source=..." providerName="System.Data.SqlClient" />
</connectionStrings>
<applicationSettings>
<App.Properties.Settings>
<setting name="LogPath" serializeAs="String">
<value>C:\Temp</value>
</setting>
</App.Properties.Settings>
<DLLSample.Properties.Settings>
<setting name="AllowStart" serializeAs="String">
<value>True</value>
</setting>
</DLLSample.Properties.Settings>
</applicationSettings>
</configuration>
From both your application and DLL code you'll be able to use the normal configuration settings mechanism, like access a value through Properties.Settings.Default.AllowStart from the DLL's code or Properties.Settings.Default.LogPath from the application's code.
Two things you can not do:
Access the DLL config values from your application and vice versa
Manage the DLLs config values from the application's property page. You need to edit the app.config manually to add/remove/modify settings.
.config files are read once on startup at runtime by the ConfigurationManager. Also if you are using a main app.config for your application you need to actually add your individual dll.config values under the correct section heading to the app.config in order for the application to pick them up at runtime.
Changing the file at runtime still will have no effect, unless you write your application to do so with manually written code (FileSystemWatcher etc). Only changing ASP.NET web.config files results in the runtime application restarting as it's a feature of ASP.NET's runtime.
I have a C# Project called Application which is basically considered to represent the top most application layer. All other Layers are treated as ClassLibraries like BUSINESS, DAO and UTIL. Now I want that the application be configurable by using the App.config file. For that purpose I need to make this configuration file visible for the referenced ClassLibraries (Assemblies).
For me, the most suitable solution would be that the UTIL assembly has access to the App.config and is able to share those accessible items to the upper application layers.
So far I tried to create a Settings.settings file in the UTIL assembly which defines one item: Name: ElemName; Type: String; Scope: Application. The App.config file which is located within the Application assembly contains the following source:
<applicationSettings>
<UTIL.Settings>
<setting name="ElemName" serializesAs="String">
<value>SomeValue</value>
</setting>
</UTIL.Settings>
</applicationSettings>
If I now try to access this property via: Settings.Default.ElemName,
the build fails with error: 'UTIL.Settings' is inaccessible due to its protection level
A further approach, to make this property visible via a helper class inside assembly UTIL
public String GetElemName()
{
return Settings.Default.ElemName;
}
fails with an: 'System.Configuration.ConfigurationErrorsException' occurred in System.Configuration.dll ... Additional information: Configuration system failed to initialize
How can I get it running? (I only need to read the configuration)
The easiest is the following:
Add the required settings in the project properties of the DLL assemblies like you would do for any normal application.
Now, a DLL doesn't actually read its own app.config. The trick is to copy the entire <applicationSettings> block from the DLLs app.config to the application's app.config and also add the respective line in the <sectionGroup> section at the top of the file.
Example: Let's assume the app.config for your DLL looks like this:
<?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="DLLSample.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
<add name="DLLSample.Properties.Settings.MyConnectionString" connectionString="Data Source=..." providerName="System.Data.SqlClient" />
</connectionStrings>
<applicationSettings>
<DLLSample.Properties.Settings>
<setting name="AllowStart" serializeAs="String">
<value>True</value>
</setting>
</DLLSample.Properties.Settings>
</applicationSettings>
</configuration>
And the app.config of your application looks like this:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="App.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<App.Properties.Settings>
<setting name="LogPath" serializeAs="String">
<value>C:\Temp</value>
</setting>
</App.Properties.Settings>
</applicationSettings>
</configuration>
After the above described changes, the application's config file should look like:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="App.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<section name="DLLSample.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
<add name="DLLSample.Properties.Settings.MyConnectionString" connectionString="Data Source=..." providerName="System.Data.SqlClient" />
</connectionStrings>
<applicationSettings>
<App.Properties.Settings>
<setting name="LogPath" serializeAs="String">
<value>C:\Temp</value>
</setting>
</App.Properties.Settings>
<DLLSample.Properties.Settings>
<setting name="AllowStart" serializeAs="String">
<value>True</value>
</setting>
</DLLSample.Properties.Settings>
</applicationSettings>
</configuration>
From both your application and DLL code you'll be able to use the normal configuration settings mechanism, like access a value through Properties.Settings.Default.AllowStart from the DLL's code or Properties.Settings.Default.LogPath from the application's code.
Two things you can not do:
Access the DLL config values from your application and vice versa
Manage the DLLs config values from the application's property page. You need to edit the app.config manually to add/remove/modify settings.
Connection strings, by the way, can also be managed that way. I've added to the examples above.
I solved this issue in a different way.
The Project called Application still contains the App.config file. All referenced assemblies (Business, DAO, UTIL, and TestAssemblies) just share the applications configuration.
How to share configuration:
Project (Business, DAO, UTIL, etc.) -> Add -> Existing Item -> 'Select' App.config -> Add As Link
Project -> Add Reference -> .NET -> System.Configuration -> OK
string configValue = ConfigurationManager.AppSettings["token"];
How the App.config file looks like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
...
<appSettings>
<add key="token" value="ConfigValue" />
</appSettings>
...
</configuration>
Without this reference to the existing App.conifg file AppSettings["token"] won't resolve the value while running with NUnit. If the application is started in debug mode, everything works fine, even without the link to App.config as mentioned by user Maarten
My question involves this simple walkthrough shown in the article Preserve Size and Location of Windows Forms – Part I by Dennis Wallentin.
This approach works 100% fine when using VB.NET. When using the same steps in C#, however, the settings within the Settings tab of the application's properties looks correct, and the app.config file looks right, but the values are not saved when you run it.
The app.config file winds up looking like this:
<?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="WindowsAppCs.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<WindowsAppCs.Properties.Settings>
<setting name="Location" serializeAs="String">
<value>0, 0</value>
</setting>
<setting name="Size" serializeAs="String">
<value>284, 262</value>
</setting>
</WindowsAppCs.Properties.Settings>
</userSettings>
</configuration>
It looks right to me, but the values do not update when running hosted within Visual Studio or when running the compiled EXE.
I am sure that something very simple needs to be added or done, but I don't know what. Does anyone have any ideas here?
Much thanks in advance...
Are you saving the settings after the form has been resized? Doesn't Windows already remember the last position and size of your form?
I am developing a .NET 3.5 Windows Forms app. I have two projects, the UI and a Library.
UI uses strongly typed settings that are stored, as usually, in the app.config file. I read them using UI.Properties.Settings class (generated by Visual Studio).
Library uses its own strongly typed Settings (the Settings.settings file that is dumped into Library.config file).
At runtime, Library settings will not reload from the Library.config file. Only UI.config file is read by the runtime. So I am stuck with default settings in Library assembly, and cannot provide values after deployment.
To summarize: for an application assembly that is not the main executable, the settings are not read at assembly load time.
I know I can use ConfigurationManager.AppSettings["value"] and this will read from the default app config file (UI.config) but what can I do if I want strongly typed settings (read with Properties.Settings class)?
Calling Library.Properties.Settings.Default.Reload() won't do it.
Thanks.
What you need to do is merge your library config sections to app.connfig. Merging config files is done by first adding elements inside the <configSections> config element, to identity the config section and then by adding the config elements inside the configuration element.
Example of merging config files:
App config:
<?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="CA3.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<CA3.Settings>
<setting name="Setting" serializeAs="String">
<value>2</value>
</setting>
</CA3.Settings>
</userSettings>
</configuration>
Library config:
<?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="CA3.Library" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<CA3.Library>
<setting name="Setting" serializeAs="String">
<value>1</value>
</setting>
</CA3.Library>
</userSettings>
</configuration>
Merged app.config containing both library and app configuration.
<?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="CA3.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="CA3.Library" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<CA3.Settings>
<setting name="Setting" serializeAs="String">
<value>2</value>
</setting>
</CA3.Settings>
<CA3.Library>
<setting name="Setting" serializeAs="String">
<value>1</value>
</setting>
</CA3.Library>
</userSettings>
</configuration>
You can only have one .config file per AppDomain. For a Windows Forms application, that .config file is the file that is named after the executable - that is: UI.exe.config in your case.
This means that while you may have the Library.dll.config file present, the configuration system is never going to pick it up.
You should merge the library's configuration settings into the application configuration file. Configuration files for libraries are not supported by the .NET framework.
Even better, redesign your library so that it does not rely on configuration files, but rather uses Imperative Configuration.