【问题标题】:How to use .NET configuration files (app.config, settings.settings) to save and restore all application data?如何使用 .NET 配置文件(app.config、settings.settings)来保存和恢复所有应用程序数据?
【发布时间】:2010-12-24 14:05:11
【问题描述】:

虽然有很多关于 .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 文件(或其他东西)?

【问题讨论】:

    标签: .net configuration import export configuration-files


    【解决方案1】:

    感谢 Manu 建议将文件读取为 XML,我一起破解了 this solution。 (它仅适用于保存为字符串的属性,例如 TextBox 的 Text 属性。例如,如果您保留 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);
            }
        }
    }
    

    【讨论】:

    • 我想知道为什么有人认为这是一个糟糕的答案,并且有人提出了一个“好”的答案。我要说的是,这段代码有效,并且没有提出其他有效的解决方案。
    • 顺便说一下,这个解决方案操作 app.config 文件。它修改了 user.config 的内存版本,该版本在应用程序关闭时传输到文件。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      由于您的 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() 代码

      【讨论】:

      • 感谢您的推荐,但您指定的路径不是更改用户设置的正确路径。此外,如果其他人想尝试这个,Load 是 XDocument 类的静态方法,因此语法是 var doc = XDocument.Load(path);。我将继续阅读和替换 XML 文件的各个部分,以查看此方法是否有效,但还没有运气。
      • 路径应该指向你的 App.config 我认为你想要操作的部分是。
      【解决方案4】:

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

      【讨论】:

      • 好的,但是那是怎么做的呢?我已经在使用设置文件在应用程序运行之间保留用户输入,但是如何将这些信息保存和恢复为单独的文件(导入/导出)?
      • 就像下面来自 Manu 的帖子,把它想象成一个 XML 文件。
      • 再一次,这是怎么做到的?我的理解是设置“文件”实际上只是 app.config,因为这是存储设置的位置。澄清?
      • 现在我对这一切有了更好的理解,我知道我想要修改的不是 app.config。我正在通过设置设计器使用应用程序设置,并将它们绑定到我的 GUI 控件中的属性。这些属性是每个用户的,因此它们存储在 user.config 中(在程序执行时生成 - 它不在 VS 解决方案中)。
      【解决方案5】:

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

      【讨论】:

      • 看来你不操作整个文件是对的:至少在内存中,除了我认为我感兴趣的“appSettings”之外,还有更多的部分。看看什么我的意思是,尝试 var currentConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal); currentConfig.Dump();在 LINQPad 中。
      • 我发现我想要更改的不是“appSettings”值,而是“userSettings”值。具体来说,它是子节点 .
      猜你喜欢
      • 2011-11-19
      • 1970-01-01
      • 1970-01-01
      • 2011-12-13
      • 1970-01-01
      • 1970-01-01
      • 2011-03-16
      • 2012-01-31
      • 2013-06-07
      相关资源
      最近更新 更多