IT story

Windows Forms 응용 프로그램에서 응용 프로그램 설정을 저장하는 방법은 무엇입니까?

hot-time 2020. 2. 9. 19:25
반응형

Windows Forms 응용 프로그램에서 응용 프로그램 설정을 저장하는 방법은 무엇입니까?


달성하고자하는 것은 매우 간단합니다. 정보를 읽는 경로를 사용하는 Windows Forms (.NET 3.5) 응용 프로그램이 있습니다. 이 경로는 내가 제공 한 옵션 양식을 사용하여 사용자가 수정할 수 있습니다.

이제 나중에 사용할 수 있도록 경로 값을 파일에 저장하려고합니다. 이것은이 파일에 저장된 많은 설정 중 하나입니다. 이 파일은 응용 프로그램 폴더에 직접 저장됩니다.

세 가지 옵션을 사용할 수 있음을 이해합니다.

  • ConfigurationSettings 파일 (appname.exe.config)
  • 기재
  • 사용자 정의 XML 파일

.NET 구성 파일이 값을 다시 저장할 것으로 예상되지 않는다는 것을 읽었습니다. 레지스트리에 관해서는 가능한 한 멀리 떨어지고 싶습니다.

이것은 사용자 정의 XML 파일을 사용하여 구성 설정을 저장해야 함을 의미합니까? 그렇다면 해당 코드 예제 (C #)를보고 싶습니다.

이 주제에 대한 다른 토론을 보았지만 여전히 명확하지 않습니다.


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 및 기타 프로젝트 유형 모두에 적용 할 수 있습니다.

설정의 범위 속성 을 설정해야합니다 . 응용 프로그램 범위를 선택하면 Settings.Default. <속성>이 읽기 전용이됩니다.


실행 파일과 동일한 디렉토리 내에 파일로 저장하려는 경우 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.ApplicationData 디렉터리 저장됩니다 .

그 옆에 .NET 2.0에서와 같이 값을 app.config파일에 다시 저장할 수 있습니다.


ApplicationSettings클래스는 app.config 파일에 설정을 저장하는 지원하지 않습니다. 의도적으로 보안이 강화 된 사용자 계정으로 실행되는 앱 (Vista UAC)은 프로그램의 설치 폴더에 대한 쓰기 권한이 없습니다.

당신은 ConfigurationManager클래스 와 시스템을 싸울 수 있습니다 . 그러나 사소한 해결 방법은 설정 디자이너로 이동하여 설정 범위를 사용자로 변경하는 것입니다. 그로 인해 어려움이 발생하는 경우 (즉, 설정은 모든 사용자와 관련이 있습니다), 권한 상승 프롬프트를 요청할 수 있도록 옵션 기능을 별도의 프로그램에 배치해야합니다. 또는 설정을 사용하여 포기하십시오.


나는 이것을 위해 만든 라이브러리를 공유하고 싶었습니다. 작은 라이브러리이지만 .settings 파일보다 큰 개선 (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();
}

.settings 파일과 비교할 때의 이점 : 코드가 상당히 적으며 각 속성을 한 번만 언급하면되므로 오류가 훨씬 적습니다 .

설정 파일을 사용하면 각 속성을 다섯언급해야합니다 . 한 번 명시 적으로 속성을 만들면 코드에서 값을 앞뒤로 복사하는 코드에 네 번 더 추가해야합니다.

스토리지, 직렬화 등을 완전히 구성 할 수 있습니다. 대상 객체가 IOC 컨테이너에 의해 생성되면, 속성을 지속적으로 만들기 위해 필요한 모든 것이 [추적 가능] 속성으로 때리기 위해 해결해야하는 모든 객체에 추적을 자동으로 적용하도록 [후크] [] 할 수 있습니다. 그 위에.

구성이 가능하고 다음을 구성 할 수 있습니다.-데이터가 전역 적으로 또는 각 추적 된 개체에 대해 지속되고 적용될 때-직렬화 방법-저장된 위치 (예 : 파일, 데이터베이스, 온라인, 격리 된 저장소, 레지스트리)-적용 / 지속을 취소 할 수있는 규칙 속성 데이터

나를 믿어 라, 도서관은 최고 수준이다!


registry / configurationSettings / XML 인수는 여전히 매우 활성화 된 것으로 보입니다. 기술이 발전함에 따라 모든 것을 사용했지만 가장 좋아하는 것은 Threed의 시스템Isolated Storage를 기반으로 합니다.

다음 샘플에서는 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 파일로 저장 한 다음 시작할 때 다시 읽는 것입니다.

다음은 폼의 위치와 크기를 저장하는 예입니다.

구성 데이터 객체는 강력하게 형식화되어 있으며 사용하기 쉽습니다.

[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.configor 사용하는 제안 된 솔루션이 마음에 들지 않습니다 app.config. 자신의 XML을 읽어보십시오. 더 이상 web.config XML 설정 파일을 살펴보십시오 .


사용자 지정 XML 파일을 사용하는 대신 다른 옵션 인 JSON 또는 YAML 파일과 같은보다 사용자 친화적 인 파일 형식을 사용할 수 있습니다.

  • .NET 4.0 동적을 사용하는 경우이 라이브러리는 사용하기가 매우 쉽습니다 (직렬화, 역 직렬화, 중첩 된 오브젝트 지원 및 원하는대로 출력을 순서화 + 여러 설정을 하나로 병합) JsonConfig (사용은 ApplicationSettingsBase와 동일)
  • .NET YAML 구성 라이브러리의 경우 ... JsonConfig만큼 사용하기 쉬운 것을 찾지 못했습니다.

Environment.SpecialFolder 열거 및 여러 파일 (기본 읽기 전용, 역할 별, 사용자 별 등)에 나열된대로 모든 사용자 및 사용자 별 여러 특수 폴더에 설정 파일을 저장할 수 있습니다 .

여러 설정을 사용하도록 선택한 경우 해당 설정을 병합 할 수 있습니다 (예 : 기본 + BasicUser + AdminUser에 대한 설정 병합). 당신은 당신의 자신의 규칙을 사용할 수 있습니다 : 마지막 규칙은 값 등을 재정의합니다.


"이것은 사용자 정의 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

도움이 되길 바랍니다.


내가 알 수있는 한 .NET은 내장 응용 프로그램 설정 기능을 사용하여 지속 설정을 지원합니다.

Windows Forms의 응용 프로그램 설정 기능을 사용하면 클라이언트 컴퓨터에서 사용자 지정 응용 프로그램 및 사용자 기본 설정을 쉽게 만들고 저장하고 유지 관리 할 수 ​​있습니다. Windows Forms 응용 프로그램 설정을 사용하면 데이터베이스 연결 문자열과 같은 응용 프로그램 데이터뿐만 아니라 사용자 응용 프로그램 기본 설정과 같은 사용자 별 데이터도 저장할 수 있습니다. Visual Studio 또는 사용자 지정 관리 코드를 사용하면 새 설정을 만들고, 디스크에서 읽고 디스크에 쓰고, 양식의 속성에 바인딩하고,로드 및 저장하기 전에 설정 데이터의 유효성을 검사 할 수 있습니다. -http : //msdn.microsoft.com/en-us/library/k4s6c3a0.aspx


때로는 전통적인 web.config 또는 app.config 파일에 보관 된 설정을 제거하고 싶을 수도 있습니다. 설정 항목의 배포 및 분리 된 데이터 디자인을보다 세밀하게 제어하려고합니다. 또는 런타임에 새 항목을 추가 할 수 있어야합니다.

두 가지 좋은 옵션을 상상할 수 있습니다.

  • 강력한 형식의 버전
  • 객체 지향 버전.

강력한 형식의 버전의 장점은 강력한 형식의 설정 이름과 값입니다. 이름이나 데이터 형식을 혼용 할 위험이 없습니다. 단점은 더 많은 설정을 코딩해야하며 런타임에 추가 할 수 없다는 것입니다.

객체 지향 버전을 사용하면 런타임에 새로운 설정을 추가 할 수 있다는 장점이 있습니다. 그러나 강력한 형식의 이름과 값이 없습니다. 문자열 식별자에주의해야합니다. 값을 얻을 때 이전에 저장된 데이터 유형을 알아야합니다.

완전한 기능 구현의 코드는 여기에서 찾을 수 있습니다 .


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

참고 URL : https://stackoverflow.com/questions/453161/how-to-save-application-settings-in-a-windows-forms-application



반응형