代码之家  ›  专栏  ›  技术社区  ›  Pat

如何使用.NET配置文件(app.config、settings.settings)保存和还原所有应用程序数据?

  •  7
  • Pat  · 技术社区  · 15 年前

    尽管有很多关于.NET配置文件的文章,但我相信我的要求不允许任何建议的解决方案(或者我不太了解使它对我有用的过程)。

    情况是,我有一个Windows窗体应用程序(也可以是另一个应用程序),它将某些用户输入字段(如IP地址)以及窗体属性(窗口大小等)绑定到应用程序设置(在“属性->设置”区域中)。据我所知,这些设置与我项目的app.config文件中表示的设置相同,因此我应该能够使用System.configuration.configurationManager类来操作这些设置。

    我要做的是允许用户导出和导入所有保存的设置。我认为保存和替换应用程序使用的配置文件会更容易,而不是对某些自定义对象进行序列化或使用ini文件。

    将当前设置保存到指定文件相对容易:

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

    但是,恢复配置文件以覆盖当前设置是很困难的。 我好像可以这样打开一个配置文件

    var newConfig = ConfigurationManager.OpenExeConfiguration(settingsFilePath)
    

    但我不知道如何用导入文件的设置完全替换当前配置中的所有设置。[编辑:此重载应该接收.exe的路径,而不是.config文件。如果调用代码未引用配置文件中的相同程序集,以这种方式打开一个exe文件可能会引发configurationErrorsException。]

    也许我只需要使用 other posts 只替换配置的一部分,而不是全部内容,但我不知道这在此时如何工作。

    有什么想法吗?我走的是正确的路线,还是应该只使用ini文件(或其他东西)?

    5 回复  |  直到 14 年前
        1
  •  3
  •   Kenoyer130    15 年前

    最好不要写入app.config,而是使用设置文件保存修改后的用户设置。app.config和web.config只能用于只读值。

        2
  •  3
  •   Manu JCasso    15 年前

    由于app.config文件是一个简单的XML文件,因此可以将其加载到xdocument中:

    string path = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
    XDocument doc = XDocument.Load(path);
    //Do your modifications to section x
    doc.Save(path);
    ConfigurationManager.RefreshSection("x");
    

    我根据@pat的注释更正了xdocument.load()代码

        3
  •  2
  •   Community CDub    8 年前

    由于我没有收到任何其他答案,也不满意我以前的解决方案,我再次问了这个问题,做了更多的研究,并能够想出一个更好的答案。见 How to load a separate Application Settings file dynamically and merge with current settings? 代码和解释。

        4
  •  1
  •   mfeingold    15 年前

    我不认为覆盖整个配置文件是一个好主意。此文件中的某些设置可能包含要在任何代码有机会执行任何操作(即与.NET CLR启动相关的操作)之前提前处理的设置。

        5
  •  0
  •   Pat    14 年前

    多亏了马努的建议,我才把文件读成XML,于是我一起黑客了。 this solution .(对于保存为字符串的属性(如文本框的文本属性),它仅在当前表单中起作用。例如,如果您保留NumericUpDown控件的Value属性,它将不起作用。)它通过使用带有要保存文件路径的export来工作,该路径生成如下文件:

    <?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>
    

    然后导入该文件,应用程序中的所有设置都会发生更改(不要忘记在某个时刻使用.save())。如果出现问题,设置将恢复。

    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);
            }
        }
    }