Dowemo
0 0 0 0


Question:

Although there are a lot of posts about .net config files, I believe that my requirements do not allow for any of the solutions proposed (or I don't understand the process enough to make it work for me).

The situation is that I have a Windows Forms application (could just as well be another app) which binds certain user input fields (e.g. IP Address), as well as form properties (window size, etc) to application settings (in the Properties->Settings area). From what I understand, these settings are the same as those represented in my project's app.config file, so I should be able to use the System.Configuration.ConfigurationManager class to manipulate those settings.

What I want to do is to allow the user to export and import all of the saved settings. Rather than doing serialization of some custom object or working with INI files, I thought it would be easier to just save and replace the config file that the application uses.

It is relatively easy to save the current settings to a specified file:

internal static void Export(string settingsFilePath)
{
    var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
    config.SaveAs(settingsFilePath);
}

However, restoring a config file to overwrite the current settings is proving difficult. It seems like I can open a configuration file like so

var newConfig = ConfigurationManager.OpenExeConfiguration(settingsFilePath)

but I don't see how to completely replace all of the settings in the current config with those of the imported file. [Edit: This overload is supposed to receive the path of the .exe, not the .config file. Opening an exe file in this manner will possibly throw a ConfigurationErrorsException if the calling code doesn't reference the same assemblies in the config file.]

Perhaps I only need to use the methods outlined in other posts to replace only a section of the config, and not the whole thing, but I don't see how that would work at this point.

Any ideas? Am I going down the right track, or should I just use INI files (or something else)?


Best Answer:


Thanks to Manu's suggestion to just read the file as XML, I hacked together this solution. (It only works in the current form for properties saved as strings, such as the Text property of a TextBox. It won't work, for instance, if you persist the Value property of a NumericUpDown control.) It works by using Export with a path to the file to save, which produces a file like the following:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <userSettings>
        <HawkConfigGUI.Properties.Settings>
            <setting name="FpgaFilePath" serializeAs="String">
                <value>testfpga</value>
            </setting>
            <setting name="FirmwareFilePath" serializeAs="String">
                <value>test</value>
            </setting>
        </HawkConfigGUI.Properties.Settings>
    </userSettings>
</configuration>

Then you Import the file and all of the settings are changed in the app (don't forget to .Save() at some point). If something goes wrong, the settings will revert back.

using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;
using AedUtils;
namespace HawkConfigGUI
{
    public static class SettingsIO
    {
        private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
        internal static void Import(string settingsFilePath)
        {
            if (!File.Exists(settingsFilePath))
            {
                throw new FileNotFoundException();
            }
            var appSettings = Properties.Settings.Default;
            try
            {
                // Open settings file as XML
                var import = XDocument.Load(settingsFilePath);
                // Get the <setting> elements
                var settings = import.XPathSelectElements("//setting");
                foreach (var setting in settings)
                {
                    string name = setting.Attribute("name").Value;
                    string value = setting.XPathSelectElement("value").FirstNode.ToString();
                    try
                    {
                        appSettings[name] = value; // throws SettingsPropertyNotFoundException
                    }
                    catch (SettingsPropertyNotFoundException spnfe)
                    {
                        _logger.WarnException("An imported setting ({0}) did not match an existing setting.".FormatString(name), spnfe);
                    }
                    catch (SettingsPropertyWrongTypeException typeException)
                    {
                        _logger.WarnException(string.Empty, typeException);
                    }
                }
            }
            catch (Exception exc)
            {
                _logger.ErrorException("Could not import settings.", exc);
                appSettings.Reload(); // from last set saved, not defaults
            }
        }
        internal static void Export(string settingsFilePath)
        {
            var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
            config.SaveAs(settingsFilePath);
        }
    }
}



Copyright © 2011 Dowemo All rights reserved.    Creative Commons   AboutUs