Thứ Hai, 15 tháng 2, 2016

Resolved: configuration system failed to initialize

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:
TypeFileLocationOccurrenceUsage/Administration
Applicationapp.configProgram Folder1 per installationVisual Studio Project Properties: Settings
Useruser.configUser Profile Folder1 per userDerivation of ApplicationSettingsBase
The usage scenario determines which type of setting to choose:
Criterion/RequirementApplication SettingUser 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:
User Settings Data Flow
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 methodUpgrade() 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.

Không có nhận xét nào:

Đăng nhận xét