code

Windows Forms 응용프로그램에 응용프로그램 설정을 저장하려면 어떻게 해야 합니까?

starcafe 2023. 9. 10. 12:27
반응형

Windows Forms 응용프로그램에 응용프로그램 설정을 저장하려면 어떻게 해야 합니까?

제가 이루고 싶은 것은 매우 간단합니다.Windows 양식(.)이 있습니다.NET 3.5) 정보 읽기 경로를 사용하는 어플리케이션이 경로는 제가 제공하는 옵션 양식을 사용하여 사용자가 수정할 수 있습니다.

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

세 가지 옵션이 가능한 것으로 알고 있습니다.

  • 구성 설정 파일(appname.exe.config)
  • 레지스트리
  • 사용자 지정 XML 파일

저는 그 글을 읽었네요.NET 구성 파일은 값을 다시 저장할 수 없습니다.등기부에 관해서는 가능한 한 멀리 떨어져 있고 싶습니다.

사용자 지정 XML 파일을 사용하여 구성 설정을 저장해야 한다는 뜻입니까?

그렇다면 그 코드 예시(C#)를 보고 싶습니다.

저는 이 주제에 대한 다른 논의들을 보았지만, 아직도 저에게는 명확하지 않습니다.

Visual Studio를 사용하면 지속 가능한 설정을 쉽게 얻을 수 있습니다.Solution Explorer에서 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 Properties(속성)를 선택합니다.설정 탭을 선택하고 설정이 없는 경우 하이퍼링크를 클릭합니다.

Settings(설정) 탭을 사용하여 응용프로그램 설정을 만듭니다.는 Visual Studio에서 파일을 .Settings.settings그리고.Settings.Designer.settings는e고n을tSettingsApplicationSettingsBase에서 상속됨.코드에서 읽기/쓰기 응용프로그램 설정으로 이 클래스에 액세스할 수 있습니다.

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

이 방법은 콘솔, Windows Forms 및 기타 프로젝트 유형에 모두 적용할 수 있습니다.

설정의 스코프 속성을 설정해야 합니다.Application scope(애플리케이션 범위)를 선택한 경우 Settings(설정).체납.<당신의 속성>은 읽기 전용이 됩니다.

참조:방법: C# - Microsoft 문서를 사용하여 런타임에 사용자 설정 쓰기

실행 파일과 동일한 디렉토리에 있는 파일에 저장하려는 경우 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 파일에 저장합니다. 이 파일은 분리 저장소 또는 특수 폴더에 저장됩니다.ApplicationData 디렉토리.

그으로 . 에 . 2 NET 2.0, 합니다 이 하는 합니다 값을 다시 할 수 .app.config파일.파일.

ApplicationSettingsclass는 app.config 파일에 설정 저장을 지원하지 않습니다.적절히 보안된 사용자 계정으로 실행되는 응용 프로그램(Vista UAC와 같이)에는 프로그램의 설치 폴더에 대한 쓰기 권한이 없습니다.

당신은 시스템과 싸울 수 있습니다.ConfigurationManagerclass.Userclass로 입니다. 하지만 사소한 해결책은 Settings 디자이너에 들어가서 User로 설정 범위를 변경하는 것입니다.문제가 발생할 경우(예: 설정이 모든 사용자와 관련됨), 권한 상승 프롬프트를 요청할 수 있도록 옵션 기능을 별도의 프로그램에 넣어야 합니다.또는 설정을 사용하여 포기합니다.

나는 이것을 위해 내가 만든 도서관을 공유하고 싶었습니다.작은 라이브러리이지만 .설정 파일에 비해 IMHO(Big Improvement)가 크게 향상되었습니다.

그 도서관은 Jot (GitHub)이라고 불립니다.여기에 제가 그것에 관해 쓴 오래된 The Code Project 기사가 있습니다.

창 크기와 위치를 추적하는 데 사용하는 방법은 다음과 같습니다.

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 컨테이너에 의해 생성되면 [Hookup][]할 수 있습니다. 그러면 대상 개체가 해결되는 모든 개체에 자동으로 추적이 적용되므로 속성을 지속적으로 유지하는 데 필요한 작업은 속성에 [Trackable] 특성을 적용하는 것뿐입니다.

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

날 믿어요, 도서관은 최고 수준이에요!

레지스트리/구성설정/XML 인수가 여전히 활성 상태인 것 같습니다.기술이 발전함에 따라 모든 것을 사용해 보았지만, 제가 가장 좋아하는 것은 Three시스템과 Isolated Storage를 결합한 것입니다.

다음 샘플에서는 속성 이름이 지정된 개체를 분리된 저장소의 파일에 저장할 수 있습니다.예:

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>

예, 구성을 저장할 수 있습니다. 구성을 저장하는 방법에 따라 거의 달라집니다.기술적 차이에 대해 설명해 드리면 다음과 같은 옵션을 이해하실 수 있습니다.

먼저 애플리케이션 설정을 사용할지 아니면 애플리케이션 설정을 사용할지 구별해야 합니다.*.exe.config ()App.config Visual Studio) 파일 - 여기 설명기본적 차이점이 있습니다.

두 가지 모두 변경사항을 저장하는 다양한 방법을 제공합니다.

  • AppSettings를 사용하면 다음을 통해 직접 구성 파일을 읽고 쓸 수 있습니다.config.Save(ConfigurationSaveMode.Modified);는 다음과 같이 됩니다. , 서 config 는 과 됩니다 됩니다 과 는 .
    config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
  • applicationSettings는 읽기를 허용하지만, 변경사항을 작성하는 경우에는Properties.Settings.Default.Save();되며, 특별한 ) 되며 로 한 로 (한:C:\Documents and Settings\USERID\Local Settings\Application Data\FIRMNAME\WindowsFormsTestApplicati_Url_tdq2oylz33rzq00sxhvxucu5edw2oghw\1.0.0.0Hans Passant가 자신의 답변에서 언급한 것처럼, 사용자는 보통 Program Files에 대한 제한된 권한을 가지고 있으며 UAC 프롬프트를 호출하지 않으면 프로그램 파일에 쓸 수 없기 때문입니다.나중에 구성 키를 추가할 경우 모든 사용자 프로필과 구성 키를 동기화해야 한다는 단점이 있습니다.

하지만 몇 가지 다른 대안이 있습니다.

  • .NET Core (및 .NET 5 및 6) 세 번째 옵션은appsettings.json(또한d)를 사용하는 파일secrets.json파일은 어셈블리 디렉터리가 아닌 사용자 프로필에 저장됩니다.하지만 보통 WinForms는 사용하지 않기 때문에, 단지 완성도를 위해 언급하는 것입니다.그러나 여기에 읽고 쓰는 방법에 대한 몇 가지 참고 자료가 있습니다.또는 Newtonsoft JSON을 사용하여 다음을 읽고 쓸 수 있습니다.appsettings.json파일이지만 이에 제한되는 것은 아닙니다. 이 메서드를 사용하여 자신의 json 파일을 만들 수도 있습니다.

  • 질문에 언급된 바와 같이,번째 옵션이 있습니다.환경설정 파일을 XML 문서로 취급할 경우 클래스를 사용하여 파일을 로드, 수정 및 저장할 수 있습니다.사용자 지정 XML 파일을 사용할 필요는 없으며 기존 구성 파일을 읽을 수 있습니다. 요소를 쿼리하려면 Linq 쿼리를 사용할 수도 있습니다.여기 를 하나 드렸는데, 답의 기능을 확인해보세요.

  • 다섯 번째 옵션은 레지스트리에 설정을 저장하는 것입니다.어떻게 할 수 있는지 여기에 설명되어 있습니다.

  • 마지막으로, 6번째 옵션이 있습니다.환경(시스템 환경 또는 계정의 환경)에 값을 저장할 수 있습니다.Windows 설정(Windows 메뉴의 톱니바퀴)에서 검색 표시줄에 "환경"을 입력하고 추가하거나 편집합니다.읽으려면 다음을 사용합니다.
    var myValue = Environment.GetEnvironmentVariable("MyVariable");.
    업데이트된 환경 설정을 얻으려면 일반적으로 응용프로그램을 다시 시작해야 합니다.

값을 보호하기 위해 암호화가 필요한 경우 이 답변을 확인하십시오.마이크로소프트의 DPAPI를 사용하여 암호화된 값을 저장하는 방법에 대해 설명합니다.

XML이든 JSON이든 자신의 파일을 지원하려면 실행 중인 어셈블리의 디렉토리를 아는 것이 유용할 수 있습니다.

var assemblyDLL = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyDirectory = System.IO.Path.GetDirectoryName(assemblyDLL.Location);

을 사용할 수 .assemblyDirectory파일을 저장하기 위한 기본 디렉토리입니다.

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

제안된 사용 솔루션이 마음에 들지 않습니다.web.config아니면app.config. 자신의 XML을 읽어 보십시오. XML Settings Files – No more web.config살펴보십시오.

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

  • 사용하시면.NET 4.0 dynamic, 이 라이브러리는 정말 사용하기 쉽습니다(직렬화, 역직렬화, 중첩 개체 지원 및 원하는 대로 출력 주문하기 + 여러 설정을 하나로 병합하기) JsonConfig(사용법은 ApplicationSettingsBase와 동일함)
  • .NET YAML 구성 라이브러리의 경우...JsonConfig만큼 쉽게 사용할 수 있는 제품을 찾지 못했습니다.

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

여러 설정을 사용하도록 선택한 경우 다음 설정을 병합할 수 있습니다.예를 들어 기본값 + BasicUser + AdminUser에 대한 설정 병합입니다.마지막 규칙이 값을 재정의하는 등 자신만의 규칙을 사용할 수 있습니다.

제가 알기로는..NET은 내장된 애플리케이션 설정 기능을 사용하여 지속 설정을 지원합니다.

Windows Forms의 Application Settings(애플리케이션 설정) 기능을 사용하면 클라이언트 컴퓨터에서 사용자 지정 애플리케이션 및 사용자 환경설정을 쉽게 만들고 저장하고 유지 관리할 수 있습니다.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-can-i-save-application-settings-in-a-windows-forms-application

반응형