Obviously, the solution is to either repair or simply delete the user.config file, but we have to find it before we can do that. I won't get into repairing, since there's no simple way that I know of to do this. In most cases, deleting the user's application settings, while inconvenient, is not the end of the world, so long as the user is given fair warning that this is about to happen. You're free to take other measures, of course.
It turns out, the path to the user.config file was in the exception all along! But, it's sneakily hidden inside an
InnerException
, and maybe this is why it eluded me at first. So, allow me to present a block of code that will basically handle this occurrence in a universal manner. You should place this block somewhere near the beginning of your application startup, before any call to Settings
is made:try
{
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
}
catch (ConfigurationErrorsException ex)
{
string filename = string.Empty;
if (!string.IsNullOrEmpty(ex.Filename))
{
filename = ex.Filename;
}
else
{
var innerEx = ex.InnerException as ConfigurationErrorsException;
if (innerEx != null && !string.IsNullOrEmpty(innerEx.Filename))
{
filename = innerEx.Filename;
}
}
if (!string.IsNullOrEmpty(filename))
{
if (System.IO.File.Exists(filename))
{
var fileInfo = new System.IO.FileInfo(filename);
var watcher
= new System.IO.FileSystemWatcher(fileInfo.Directory.FullName, fileInfo.Name);
System.IO.File.Delete(filename);
isReset = true;
if (System.IO.File.Exists(filename))
{
watcher.WaitForChanged(System.IO.WatcherChangeTypes.Deleted);
}
}
}
}
ConfigurationErrorsException is the correct exception to throw in the situation you describe. An earlier version of the MSDN documentation for ConfigurationErrorsException makes more sense.
The earlier MSDN summary and remarks are:
- The exception that is thrown when a configuration-system error has occurred.
- The ConfigurationErrorsException exception is thrown when any error occurs while configuration information is being read or written.
Since CLR 2.0, the .NET Framework offers an extensive configuration module in
System.Configuration
. It differentiates between program and user settings:Type | File | Location | Occurrence | Usage/Administration |
Application | app.config | Program Folder | 1 per installation | Visual Studio Project Properties: Settings |
User | user.config | User Profile Folder | 1 per user | Derivation of ApplicationSettingsBase |
The usage scenario determines which type of setting to choose:
Criterion/Requirement | Application Setting | User Setting |
Setting is the same for all users (e.g., database connection) | x | |
Setting can vary per user (e.g., theme) | x | |
Temporary/local setting (e.g., location and size of a window) | x | |
Storage of user input or selection (e.g., text alignment) | x | |
Necessity to store settings fine grained (e.g., per plug-in) | x |
Control over the user settings is gained through inheriting from the class
ApplicationSettingsBase
. A single setting value can be defined via a property and a property attribute. The methods Reload()
, Reset()
, Save()
, and Upgrade()
determine the runtime behavior. The following illustration shows the data flow of the .NET user configuration:
The 'Default Value' is defined through the property attribute
DefaultSettingValueAttribute
. The value 'Init Value' is controlled by the .NET Framework. Access to the value of 'Session Value' occurs through the property which is marked with the UserScopedSettingAttribute
, which in turn usesApplicationSettingsBase.Item
.
The methods
Reload()
and Reset()
support freshly loading all settings and setting them back to their 'Default Values, respectively.
When performing the first
Save()
, all user settings get stored in the XML file user.config. With every following program launch, the .NET Framework automatically loads them again (action Start). Where that configuration file will be located is influenced by several factors:- Profile Directory: The local or roaming profile directory (e.g., C:\Documents and Settings\MyName)
- Company Name: The value of the
AssemblyCompanyAttribute
in AssemblyInfo.cs - App Name: The value of the
AssemblyProductAttribute
in AssemlyInfo.cs - Evidence Type and Evidence Hash: Information derived from the app domain evidence
- Version: The value of the
AssemblyVersionAttribute
in AssemblyInfo.cs
If any of these factors change, the user settings will be stored (and looked for) in a different folder. The method
Upgrade()
offers some support for migrating user settings from previous versions. Care should be taken, however, when changing either the company or the application name, as these changes will prevent future upgrades.