Рекомендуется сохранять параметры приложения в приложении Windows Forms [закрыто]

то, что я хочу достичь, очень просто: у меня есть приложение Windows Forms (.NET 3.5), которое использует путь для чтения информации. Этот путь может быть изменен пользователем с помощью формы параметры, которую я предоставляю.

теперь я хочу сохранить значение пути в файл для последующего использования. Это будет один из многих параметров, сохраненных в этом файле. Этот файл будет находиться непосредственно в папке приложения.

Я понимаю, что три варианта доступно:

  • файл ConfigurationSettings (appname.исполняемый.config)
  • реестр
  • пользовательский XML-файл

Я прочитал, что файл конфигурации .NET не предусмотрен для сохранения значений обратно в него. Что касается реестра, я хотел бы уйти от него как можно дальше.

означает ли это, что я должен использовать пользовательский XML-файл для сохранения параметров конфигурации? Если это так, я хотел бы увидеть пример кода этого (С.)#

Я видел другие дискуссии на эту тему, но мне все еще не ясно.

13 ответов


если вы работаете с Visual Studio, то довольно легко получить устойчивые настройки. Щелкните правой кнопкой мыши проект в обозревателе решений, выберите Свойства. Выберите вкладку Настройки, нажмите на гиперссылку, если настройки не существуют. Используйте вкладку Параметры для создания параметров приложения. Visual Studio создает файлы Settings.settings и Settings.Designer.settings, которые содержат одноэлементный класс Settings наследуется от ApplicationSettingsBase. Вы можете получить доступ к этому классу из кода для чтения/записи настройки приложения:

Properties.Settings.Default["SomeProperty"] = "Some Value";
Properties.Settings.Default.Save(); // Saves settings in application configuration file

этот метод применим как для консоли, Windows Forms, так и для других типов проектов.

обратите внимание, что вам нужно установить область свойства параметры. Если выбрать область приложения, то параметры.По умолчанию. будет доступен только для чтения.


Если вы планируете сохранить файл в том же каталоге, что и исполняемый файл, вот хорошее решение, которое использует JSON:

using System;
using System.IO;
using System.Web.Script.Serialization;

namespace MiscConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            MySettings settings = MySettings.Load();
            Console.WriteLine("Current value of 'myInteger': " + settings.myInteger);
            Console.WriteLine("Incrementing 'myInteger'...");
            settings.myInteger++;
            Console.WriteLine("Saving settings...");
            settings.Save();
            Console.WriteLine("Done.");
            Console.ReadKey();
        }

        class MySettings : AppSettings<MySettings>
        {
            public string myString = "Hello World";
            public int myInteger = 1;
        }
    }

    public class AppSettings<T> where T : new()
    {
        private const string DEFAULT_FILENAME = "settings.json";

        public void Save(string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(this));
        }

        public static void Save(T pSettings, string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(pSettings));
        }

        public static T Load(string fileName = DEFAULT_FILENAME)
        {
            T t = new T();
            if(File.Exists(fileName))
                t = (new JavaScriptSerializer()).Deserialize<T>(File.ReadAllText(fileName));
            return t;
        }
    }
}

реестре нет. Вы не уверены, имеет ли пользователь, который использует ваше приложение, достаточные права для записи в реестр.

можно использовать app.config файл для сохранения настроек уровня приложения (которые одинаковы для каждого пользователя, использующего приложение).

Я буду хранить пользовательские настройки в XML-файле, который будет сохранен в Изолированное Хранилище или SpecialFolder.Данные приложения справочник.

рядом с этим, как из .NET 2.0, можно хранить значения обратно в .


на ApplicationSettings класс не поддерживает сохранение настроек приложения.конфигурационный файл. Это очень много по дизайну, приложения, которые работают с должным образом защищенной учетной записью пользователя (думаю, Vista UAC), не имеют доступа на запись в папку установки программы.

Вы можете бороться с системой с ConfigurationManager класса. Но тривиальный обходной путь-войти в конструктор настроек и изменить область настройки на User. Если это вызывает трудности (скажем, настройка актуальна для каждого пользователя), вы следует поместить функцию Options в отдельную программу, чтобы вы могли запросить запрос на повышение привилегий. Или отказаться от использования настроек.


Я хотел поделиться библиотекой, которую я построил для этого. Это крошечная библиотека, но большое улучшение (IMHO).файл настроек.

библиотека называется Jot (GitHub), вот статья проекта кода я писал об этом.

вот как вы могли бы использовать его для отслеживания размера и местоположения окна:

public MainWindow()
{
    InitializeComponent();

    _stateTracker.Configure(this)
        .IdentifyAs("MyMainWindow")
        .AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState))
        .RegisterPersistTrigger(nameof(Closed))
        .Apply();
}

преимущество по сравнению с.файлы настроек: там значительно меньше кода, и это много меньше ошибок, так как вам нужно только упомянуть каждое свойство после.

с файлами настроек вам нужно упомянуть каждое свойство пять times: один раз, когда вы явно создаете свойство и дополнительные четыре раза в коде, который копирует значения взад и вперед.

хранение, сериализация и т. д. полностью настраиваются. При использовании инверсия управления, вы можете подключить его так, чтобы он применял отслеживание автоматически для всех объектов он разрешает так, что все, что вам нужно сделать, чтобы сделать свойство постоянным, - это ударить по нему атрибутом [Trackable].

Я пишу все это, потому что я думаю, что библиотека на высшем уровне, и я хотел бы популяризировать его:)


аргумент registry/configurationSettings/XML по-прежнему кажется очень активным. Я использовал их все, поскольку технология прогрессировала, но мой любимый основан на Threed все!--5--> в сочетании с Изолированное Хранилище.

следующий пример позволяет хранить объекты с именем properties в файле в изолированном хранилище. Например:

AppSettings.Save(myobject, "Prop1,Prop2", "myFile.jsn");

свойства могут быть восстановлены с помощью:

AppSettings.Load(myobject, "myFile.jsn");

это просто образец, не предполагающий наилучшие виды практики.

internal static class AppSettings
{
    internal static void Save(object src, string targ, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = src.GetType();

        string[] paramList = targ.Split(new char[] { ',' });
        foreach (string paramName in paramList)
            items.Add(paramName, type.GetProperty(paramName.Trim()).GetValue(src, null));

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify.
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Create, storage))
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write((new JavaScriptSerializer()).Serialize(items));
            }

        }
        catch (Exception) { }   // If fails - just don't use preferences
    }

    internal static void Load(object tar, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = tar.GetType();

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Open, storage))
            using (StreamReader reader = new StreamReader(stream))
            {
                items = (new JavaScriptSerializer()).Deserialize<Dictionary<string, object>>(reader.ReadToEnd());
            }
        }
        catch (Exception) { return; }   // If fails - just don't use preferences.

        foreach (KeyValuePair<string, object> obj in items)
        {
            try
            {
                tar.GetType().GetProperty(obj.Key).SetValue(tar, obj.Value, null);
            }
            catch (Exception) { }
        }
    }
}

простой способ-использовать объект данных конфигурации, сохранить его как XML-файл с именем приложения в локальной папке и при запуске прочитать его обратно.

вот пример для хранения позиции и размера формы.

конфигурация dataobject строго типизирована и проста в использовании:

[Serializable()]
public class CConfigDO
{
    private System.Drawing.Point m_oStartPos;
    private System.Drawing.Size m_oStartSize;

    public System.Drawing.Point StartPos
    {
        get { return m_oStartPos; }
        set { m_oStartPos = value; }
    }

    public System.Drawing.Size StartSize
    {
        get { return m_oStartSize; }
        set { m_oStartSize = value; }
    }
}

класс менеджера для сохранения и загрузки:

public class CConfigMng
{
    private string m_sConfigFileName = System.IO.Path.GetFileNameWithoutExtension(System.Windows.Forms.Application.ExecutablePath) + ".xml";
    private CConfigDO m_oConfig = new CConfigDO();

    public CConfigDO Config
    {
        get { return m_oConfig; }
        set { m_oConfig = value; }
    }

    // Load configuration file
    public void LoadConfig()
    {
        if (System.IO.File.Exists(m_sConfigFileName))
        {
            System.IO.StreamReader srReader = System.IO.File.OpenText(m_sConfigFileName);
            Type tType = m_oConfig.GetType();
            System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
            object oData = xsSerializer.Deserialize(srReader);
            m_oConfig = (CConfigDO)oData;
            srReader.Close();
        }
    }

    // Save configuration file
    public void SaveConfig()
    {
        System.IO.StreamWriter swWriter = System.IO.File.CreateText(m_sConfigFileName);
        Type tType = m_oConfig.GetType();
        if (tType.IsSerializable)
        {
            System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
            xsSerializer.Serialize(swWriter, m_oConfig);
            swWriter.Close();
        }
    }
}

теперь вы можете создать экземпляр и использовать в загрузке и закрытии формы события:

    private CConfigMng oConfigMng = new CConfigMng();

    private void Form1_Load(object sender, EventArgs e)
    {
        // Load configuration
        oConfigMng.LoadConfig();
        if (oConfigMng.Config.StartPos.X != 0 || oConfigMng.Config.StartPos.Y != 0)
        {
            Location = oConfigMng.Config.StartPos;
            Size = oConfigMng.Config.StartSize;
        }
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        // Save configuration
        oConfigMng.Config.StartPos = Location;
        oConfigMng.Config.StartSize = Size;
        oConfigMng.SaveConfig();
    }

и полученный XML-файл также читается:

<?xml version="1.0" encoding="utf-8"?>
<CConfigDO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <StartPos>
    <X>70</X>
    <Y>278</Y>
  </StartPos>
  <StartSize>
    <Width>253</Width>
    <Height>229</Height>
  </StartSize>
</CConfigDO>

мне не нравится предлагаемое решение использования web.config или app.config. Попробуйте прочитать свой собственный XML. Взгляните на XML-файлы настроек - больше нет интернета.config.


насколько я могу судить, .NET поддерживает сохранение настроек с помощью встроенного средства настройки приложений:

функция настройки приложений Windows Forms позволяет легко создавать, хранить и поддерживать пользовательские настройки приложений и пользователей на клиентском компьютере. С помощью параметров приложения Windows Forms можно хранить не только данные приложения, такие как строки подключения к базе данных, но и пользовательские данные, такие как параметры приложения пользователя. С помощью Visual Studio или пользовательский управляемый код можно создавать новые параметры, считывать их и записывать на диск, привязывать к свойствам форм и проверять данные параметров перед загрузкой и сохранением. - http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx


другие параметры, вместо использования пользовательского XML-файла, мы можем использовать более удобный формат файла: JSON или YAML-файл.

  • Если вы используете .NET 4.0 dynamic, эта библиотека очень проста в использовании (сериализация, десериализация, поддержка вложенных объектов и упорядочение вывода как вы хотите + слияние нескольких настроек в один)JsonConfig (использование эквивалентно ApplicationSettingsBase)
  • для библиотеки конфигурации .NET YAML... Я не нашел тот, который, как простой для использования в качестве JsonConfig

вы можете хранить файл настроек в нескольких специальных папках (для всех пользователей и для каждого пользователя), как указано здесь окружающая среда.Перечисление SpecialFolder и несколько файлов (по умолчанию только для чтения, для каждой роли, для каждого пользователя и т. д.)

Если вы решите использовать несколько настроек, вы можете объединить их параметры: например, объединение параметров по умолчанию + BasicUser + AdminUser. Вы можете использовать свои собственные правила: последний переопределяет значение, и т. д.


иногда вы хотите избавиться от этих настроек в традиционном интернете.config или app.конфигурационный файл. Требуется более точный контроль над развертыванием записей параметров и разделенным дизайном данных. Или требуется включить добавление новых записей во время выполнения.

Я могу представить два варианта:

  • строго типизированная версия и
  • объектно-ориентированная версия.

преимущества строго типизированных version-это строго типизированные имена и значения параметров. Нет риска смешивания имен или типов данных. Недостатком является то, что дополнительные параметры должны быть закодированы, не могут быть добавлены во время выполнения.

с объектно-ориентированной версией преимущество заключается в том, что новые настройки могут быть добавлены во время выполнения. Но у вас нет строго типизированных имен и значений. Необходимо быть осторожным со строковыми идентификаторами. Должен знать тип данных, сохраненный ранее при получении значения.

вы можете найти код обе полнофункциональные реализации здесь.


" означает ли это, что я должен использовать пользовательский XML-файл для сохранения параметров конфигурации?"Нет, не обязательно. Для таких операций мы используем SharpConfig.

например, если файл конфигурации такой

[General]
# a comment
SomeString = Hello World!
SomeInteger = 10 # an inline comment

мы можем получить значения такой

var config = Configuration.LoadFromFile("sample.cfg");
var section = config["General"];

string someString = section["SomeString"].StringValue;
int someInteger = section["SomeInteger"].IntValue;

Он совместим с .Net 2.0 и выше. Мы можем создавать файлы конфигурации на лету, и мы можем сохранить его позже. Источник: http://sharpconfig.net/ На GitHub: https://github.com/cemdervis/SharpConfig

надеюсь, это поможет.


public static class SettingsExtensions
{
    public static bool TryGetValue<T>(this Settings settings, string key, out T value)
    {
        if (settings.Properties[key] != null)
        {
            value = (T) settings[key];
            return true;
        }

        value = default(T);
        return false;
    }

    public static bool ContainsKey(this Settings settings, string key)
    {
        return settings.Properties[key] != null;
    }

    public static void SetValue<T>(this Settings settings, string key, T value)
    {
        if (settings.Properties[key] == null)
        {
            var p = new SettingsProperty(key)
            {
                PropertyType = typeof(T),
                Provider = settings.Providers["LocalFileSettingsProvider"],
                SerializeAs = SettingsSerializeAs.Xml
            };
            p.Attributes.Add(typeof(UserScopedSettingAttribute), new UserScopedSettingAttribute());
            var v = new SettingsPropertyValue(p);
            settings.Properties.Add(p);
            settings.Reload();
        }
        settings[key] = value;
        settings.Save();
    }
}