Как использовать конфигурационные файлы .NET(app.config, settings.settings) для сохранения и восстановления всех данных приложения?
Несмотря на то, что есть много сообщений о файлах конфигурации .net, я считаю, что мои требования не позволяют ни одного из предложенных решений (или я не понимаю процесс, достаточный для того, чтобы он работал у меня).
Ситуация заключается в том, что у меня есть приложение Windows Forms (может также быть другим приложением), которое связывает определенные пользовательские поля ввода (например, 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)
но я не вижу, как полностью заменить все настройки в текущей конфигурации на файлы импортированного файла. [Edit: эта перегрузка должна получать путь к .exe, а не к .config файл. Открытие exe файла таким образом, возможно, приведет к исключению ConfigurationErrorsException, если вызывающий код не ссылается на те же сборки в файле конфигурации.]
Возможно, мне нужно только использовать методы, описанные в других сообщениях, чтобы заменить только раздел конфигурации, а не все, но я не вижу как это будет работать в этой точке.
Любые идеи? Я иду по правильному пути, или я должен просто использовать INI файлы (или что-то еще)?
Ответы
Ответ 1
Поскольку я не получил никаких других ответов и не был доволен своим предыдущим решением, я снова задал вопрос, сделал еще несколько исследований и смог найти лучший ответ. См. Как загрузить отдельный файл параметров приложения динамически и слить с текущими настройками? для кода и объяснений.
Ответ 2
Поскольку файл 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");
Я скорректировал код XDocument.Load() в соответствии с комментарием @Pat
Ответ 3
Лучше всего НЕ писать в app.config, но использовать файл настроек для сохранения пользовательских настроек, которые были изменены. Параметры app.config и web.config должны использоваться только для значений только для чтения.
Ответ 4
Я не думаю, что переопределение всего файла конфигурации - хорошая идея. Некоторые параметры в этом файле могут содержать параметры, которые будут обрабатываться на самом деле раньше, прежде чем какой-либо из ваших кодов мог бы сделать что-либо, то есть связанные с запуском .NET CLR.
Ответ 5
Благодаря предложению Ману просто прочитать файл как XML, я взломал это решение. (Он работает только в текущей форме для свойств, сохраненных в виде строк, таких как свойство Text для TextBox. Он не будет работать, например, если вы сохраняете свойство Value элемента управления NumericUpDown.) Он работает с использованием Export with путь к файлу для сохранения, который создает файл следующего вида:
<?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);
}
}
}