Jak mogę zapisać ustawienia aplikacji w aplikacji Windows Forms?

581

To, co chcę osiągnąć, jest bardzo proste: mam aplikację Windows Forms (.NET 3.5), która używa ścieżki do odczytu informacji. Ścieżkę tę może zmodyfikować użytkownik, korzystając z formularza opcji, który podaję.

Teraz chcę zapisać wartość ścieżki do pliku do późniejszego wykorzystania. To byłoby jedno z wielu ustawień zapisanych w tym pliku. Ten plik byłby umieszczony bezpośrednio w folderze aplikacji.

Rozumiem, że dostępne są trzy opcje:

  • Plik ConfigurationSettings (appname.exe.config)
  • Rejestr
  • Niestandardowy plik XML

Przeczytałem, że plik konfiguracyjny .NET nie jest przewidziany do zapisywania w nim wartości. Jeśli chodzi o rejestr, chciałbym oddalić się od niego jak najdalej.

Czy to oznacza, że ​​powinienem użyć niestandardowego pliku XML, aby zapisać ustawienia konfiguracji?

Jeśli tak, chciałbym zobaczyć przykład tego kodu (C #).

Widziałem inne dyskusje na ten temat, ale wciąż nie jest to dla mnie jasne.

Tankowane
źródło
Czy jest to aplikacja .NET WinForms? Jeśli tak, w jakiej wersji .NET opracowujesz?
Portman
1
Tak, jest to aplikacja WinForms w .NET Framework w wersji 3.5.
Tankował
1
potrzebujesz zapisać wartości haseł lub tajemnic ? Może wymaga szyfrowania
Kiquenet,

Odpowiedzi:

593

Jeśli pracujesz z Visual Studio, łatwo jest uzyskać trwałe ustawienia. Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierz Właściwości. Wybierz kartę Ustawienia i kliknij hiperłącze, jeśli ustawienia nie istnieją.

Użyj karty Ustawienia, aby utworzyć ustawienia aplikacji. Visual Studio tworzy pliki Settings.settingsi Settings.Designer.settingsktóre zawierają klasę singleton Settingsodziedziczoną ApplicationSettingsBase . Możesz uzyskać dostęp do tej klasy ze swojego kodu, aby odczytać / zapisać ustawienia aplikacji:

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

Ta technika ma zastosowanie zarówno w przypadku konsoli, formularzy Windows i innych typów projektów.

Pamiętaj, że musisz ustawić właściwość scope swoich ustawień. Jeśli wybierzesz zakres aplikacji, wówczas Settings.Default. <Twoja właściwość> będzie tylko do odczytu.

Odniesienia: Porady: Zapisywanie ustawień użytkownika w czasie wykonywania za pomocą C # - Dokumenty Microsoft

aku
źródło
2
jeśli mam rozwiązanie, czy dotyczy to całego rozwiązania czy każdego projektu?
franko_camron
8
@Four: Mam tutaj projekt .NET 4.0 WinApp, a moja SomeProperty nie jest tylko do odczytu. Settings.Default.SomeProperty = 'value'; Settings.Default.Save();działa jak marzenie. A może dlatego, że mam ustawienia użytkownika?
doekman
4
@Four: Kiedy zmieniłem ustawienie z User na Application-scope i zapisałem plik, zobaczyłem w wygenerowanym kodzie, że seter zniknął. Dzieje się tak również z profilem klienta 4.0 ...
doekman,
3
@ Four: świetny link, choć twoje stwierdzenie, że Settings.Default.Save()nic nie robi, jest nieprawidłowe. Jak stwierdza @aku w odpowiedzi, ustawienia zakresu aplikacji są tylko do odczytu: zapisywanie jest dla nich nieskuteczne. Użyj tego niestandardowego PortableSettingsProvider, aby zapisać ustawienia zakresu użytkownika w pliku app.config, w którym znajduje się plik exe zamiast tego w folderze AppData użytkownika. Nie, ogólnie nie jest dobre, ale używam go podczas programowania, aby używać tych samych ustawień od kompilacji do kompilacji (bez niego, idą nowe unikalne foldery użytkownika z każdą kompilacją).
minnow
7
Na razie w .NET 3.5 wydaje się, że możesz po prostu użyć Settings.Default.SomeProperty, aby przypisać wartość i uzyskać mocne rzutowanie. Ponadto, aby zaoszczędzić czas innym (zajęło mi to trochę czasu, aby to rozgryźć), musisz wpisać Properties.Settings.Default lub dodać za pomocą YourProjectNameSpace.Settings na górze pliku. Same „Ustawienia” nie zostały zdefiniowane / znalezione.
eselk
94

Jeśli planujesz zapisać do pliku w tym samym katalogu co plik wykonywalny, oto fajne rozwiązanie, które używa formatu 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;
        }
    }
}
Trevor
źródło
Tak, zmień DEFAULT_FILENAME na ścieżkę bezwzględną, jeśli chcesz zapisać w innym katalogu. Myślę, że najczęściej zapisuje się plik w tym samym katalogu co aplikacja lub podkatalog, jeśli nie zapisujesz ich w rejestrze.
Trevor
Och, być może lepszą opcją byłoby przechowywanie pliku ustawień w folderze appdata użytkownika.
Trevor
1
Nie trzeba się zmieniać DEFAULT_FILENAME, wystarczy zadzwonić settings.Save(theFileToSaveTo); Będąc wszystkimi czapkami, DEFAULT_FILENAMEma być stałą . Jeśli chcesz mieć właściwość do odczytu i zapisu, utwórz ją i ustaw na nią konstruktor DEFAULT_FILENAME. Następnie ustaw domyślną wartość argumentu na: nullprzetestuj ją i użyj swojej właściwości jako wartości domyślnej. To trochę więcej pisania, ale daje bardziej standardowy interfejs.
Jesse Chisholm
10
Będziesz musiał odwołać się, System.Web.Extensions.dlljeśli jeszcze tego nie masz.
TEK
9
Stworzyłem całą bibliotekę w oparciu o tę odpowiedź z wieloma ulepszeniami i udostępniłem ją w nuget
NucS
67

Rejestr jest nie do przejścia. Nie masz pewności, czy użytkownik korzystający z Twojej aplikacji ma wystarczające uprawnienia do zapisu w rejestrze.

Możesz użyć tego app.configpliku do zapisania ustawień na poziomie aplikacji (które są takie same dla każdego użytkownika korzystającego z Twojej aplikacji).

Zapisałbym ustawienia użytkownika w pliku XML, który zostałby zapisany w Izolowanym magazynie lub w katalogu SpecialFolder.ApplicationData .

Oprócz tego, począwszy od .NET 2.0, możliwe jest przechowywanie wartości z powrotem do app.configpliku.

Frederik Gheysels
źródło
8
Użyj rejestru, jeśli chcesz ustawić ustawienia logowania / użytkownika.
wtedyonhacker
19
Rejestru nie można przenosić
Kb.
10
@thenonhacker: Lub użyj Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData)
Kenny Mann
4
Do rejestru użytkowników można zapisać (wiele programów zapisuje tam informacje, a uprawnienia użytkowników nigdy nie stanowią problemu). Zaletą korzystania z rejestru nad korzystaniem z ustawień jest to, że jeśli masz wiele aplikacji współużytkujących ten sam folder (np. Program instalacyjny i program aplikacyjny), nie będą one współużytkować tych samych ustawień.
Kesty
3
Główną wadą Rejestru jest trudny sposób eksportowania / kopiowania ustawień na inny komputer. Ale nie zgadzam się z „Nie jesteś pewien, czy użytkownik korzystający z Twojej aplikacji ma wystarczające uprawnienia do zapisu do rejestru” - W HKEY_CURRENT_USER zawsze masz prawa do zapisu. Można odmówić, ale system plików może być niedostępny dla bieżącego użytkownika (wszystkie możliwe foldery TEMP itp.).
i486,
20

ApplicationSettingsKlasa nie obsługuje zapisywania ustawień do app.config pliku. To bardzo z założenia; aplikacje działające z odpowiednio zabezpieczonym kontem użytkownika (patrz Vista UAC) nie mają dostępu do zapisu w folderze instalacyjnym programu.

Możesz walczyć z systemem z ConfigurationManagerklasą. Ale trywialnym obejściem jest przejście do projektanta ustawień i zmiana zakresu ustawienia na użytkownika. Jeśli powoduje to trudności (powiedzmy, ustawienie dotyczy każdego użytkownika), należy umieścić funkcję Opcje w osobnym programie, aby można było poprosić o monit o podniesienie uprawnień. Lub zrezygnuj z używania ustawienia.

Hans Passant
źródło
Czy możesz rozwinąć swoje ostatnie zdanie? Poproś o podniesienie uprawnień, aby napisać app.config lub napisać osobną aplikację, która przejdzie przez domowe folery wszystkich użytkowników, poszukaj user.config i edytujesz je?
CannibalSmith
2
Odrębny program wymaga manifestu z prośbą o podniesienie. Google „asinvoker wymaga administratora”, aby znaleźć odpowiednią składnię. Edycja user.config nie jest praktyczna ani konieczna.
Hans Passant
18

Argument register / configurationSettings / XML nadal wydaje się bardzo aktywny. Wykorzystałem je wszystkie, w miarę postępu technologii, ale mój ulubiony oparty jest na systemie Threeda w połączeniu z Isolated Storage .

Poniższy przykład umożliwia przechowywanie obiektów o nazwie właściwości do pliku w pamięci izolowanej. Jak na przykład:

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

Właściwości można odzyskać za pomocą:

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

To tylko próbka, nie sugerująca najlepszych praktyk.

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) { }
        }
    }
}
Boczek
źródło
1
Lub jeszcze lepiej; użyj DataContractJsonSerializer
Boczek
16

Chciałem udostępnić bibliotekę, którą dla tego stworzyłem. To niewielka biblioteka, ale duże ulepszenie (IMHO) w stosunku do plików .settings.

Biblioteka nazywa się Jot (GitHub) . Oto stary artykuł The Code Project , który o nim napisałem.

Oto, w jaki sposób możesz go użyć do śledzenia rozmiaru i lokalizacji okna:

public MainWindow()
{
    InitializeComponent();

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

Korzyść w porównaniu z plikami .settings: kod jest znacznie mniejszy i jest znacznie mniej podatny na błędy, ponieważ każdą właściwość trzeba podać tylko raz .

W przypadku plików ustawień należy pięć razy wspomnieć o każdej właściwości : raz, gdy jawnie utworzysz właściwość i dodatkowe cztery razy w kodzie, który kopiuje wartości w tę iz powrotem.

Pamięć masowa, serializacja itp. Są w pełni konfigurowalne. Gdy obiekty docelowe są tworzone przez kontener IoC , możesz [podłączyć go] [], aby automatycznie zastosował śledzenie do wszystkich obiektów, które rozwiązuje, tak aby wszystko, co musisz zrobić, aby zachować trwałość właściwości, to uderzenie w [Trackable] atrybut na to.

Jest wysoce konfigurowalny i możesz skonfigurować: - kiedy dane są utrwalane i stosowane globalnie lub dla każdego śledzonego obiektu - jak są serializowane - gdzie są przechowywane (np. Plik, baza danych, online, pamięć izolowana, rejestr) - reguły, które mogą anulować zastosowanie / utrwalanie danych dla właściwości

Zaufaj mi, biblioteka jest na najwyższym poziomie!

anakic
źródło
14

Prostym sposobem jest użycie obiektu danych konfiguracji, zapisanie go jako plik XML z nazwą aplikacji w folderze lokalnym i po uruchomieniu odczyta go ponownie.

Oto przykład przechowywania pozycji i rozmiaru formularza.

Obiekt danych konfiguracji jest silnie typowany i łatwy w użyciu:

[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; }
    }
}

Klasa menedżera do zapisywania i ładowania:

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

Teraz możesz utworzyć instancję i użyć w formularzu zdarzeń ładowania i zamykania:

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

Utworzony plik XML jest także czytelny:

<?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>
Dieter Meemken
źródło
1
Mam to świetnie działające w fazie programowania, ale podczas wdrażania aplikacji przeciętny użytkownik nie ma dostępu do c:\program files\my applicationfolderu, więc zapisanie ustawień powoduje błąd. Zastanawiam się nad zapisaniem pliku xml w AppData, ale po prostu zastanawiałem się, czy istnieje oczywisty sposób na obejście tego problemu, ponieważ wydaje się, że to podejście zadziałało.
Philip Stratford
@PhilipStratford Ponieważ jest to zwykły plik, można go zapisać w dowolnym miejscu. Po prostu znajdź miejsce z dostępem do zapisu.
Dieter Meemken
@PhilipStratford Może być folderem AppData jest opcją dla Ciebie, zobacz C # pobieranie ścieżki% AppData% , jak wspomniano przez latawiec .
Dieter Meemken
Dzięki, już to zaimplementowałem, zapisując plik xml w folderze AppDate. Zastanawiałem się tylko, czy istnieje prosty sposób na zapisanie go w folderze aplikacji zgodnie z twoim przykładem, ponieważ zakładałem, że udało ci się go uruchomić. Nie martw się, folder AppData i tak jest prawdopodobnie lepszą lokalizacją!
Philip Stratford,
7

Nie podoba mi się proponowane rozwiązanie polegające na użyciu web.configlub app.config. Spróbuj przeczytać swój własny XML. Spójrz na pliki ustawień XML - koniec z web.config .

gatapia
źródło
5

Inne opcje, zamiast używać niestandardowego pliku XML, możemy użyć bardziej przyjaznego formatu pliku: JSON lub YAML.

  • Jeśli korzystasz z .NET 4.0 dynamic, ta biblioteka jest naprawdę łatwa w użyciu (serializacja, deserializacja, obsługa obiektów zagnieżdżonych i porządkowanie danych wyjściowych według własnego uznania + scalanie wielu ustawień w jedno) JsonConfig (użycie jest równoważne z ApplicationSettingsBase)
  • Dla biblioteki konfiguracji .NET YAML ... Nie znalazłem takiej, która byłaby tak łatwa w użyciu jak JsonConfig

Możesz zapisać plik ustawień w wielu specjalnych folderach (dla wszystkich użytkowników i na użytkownika), jak podano tutaj. Środowisko. Specjalne wyliczanie folderów i wiele plików (domyślnie tylko do odczytu, na rolę, na użytkownika itp.)

Jeśli wybierzesz użycie wielu ustawień, możesz scalić te ustawienia: Na przykład scalając ustawienia dla domyślnego + BasicUser + AdminUser. Możesz użyć własnych reguł: ostatnia przesłania wartość itp.

latawiec
źródło
4

„Czy to oznacza, że ​​powinienem użyć niestandardowego pliku XML do zapisania ustawień konfiguracji?” Nie, niekoniecznie. Do takich operacji używamy SharpConfig.

Na przykład, jeśli plik konfiguracyjny jest taki

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

Możemy pobrać takie wartości

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

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

Jest kompatybilny z .NET 2.0 i nowszymi wersjami. Pliki konfiguracyjne możemy tworzyć w locie i możemy zapisać później.

Źródło: http://sharpconfig.net/
GitHub: https://github.com/cemdervis/SharpConfig

Turker Tunali
źródło
3

O ile mi wiadomo, .NET obsługuje utrzymywanie ustawień przy użyciu wbudowanej funkcji ustawień aplikacji:

Funkcja Ustawienia aplikacji Windows Forms ułatwia tworzenie, przechowywanie i utrzymywanie niestandardowych preferencji aplikacji i użytkowników na komputerze klienckim. Dzięki ustawieniom aplikacji Windows Forms możesz przechowywać nie tylko dane aplikacji, takie jak parametry połączenia z bazą danych, ale także dane specyficzne dla użytkownika, takie jak preferencje aplikacji użytkownika. Za pomocą programu Visual Studio lub niestandardowego kodu zarządzanego można tworzyć nowe ustawienia, odczytywać je i zapisywać na dysku, wiązać je z właściwościami formularzy oraz sprawdzać dane ustawień przed załadowaniem i zapisaniem. - http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx

Jakub
źródło
2
Nieprawda .. patrz odpowiedź Aku powyżej. jest to możliwe przy użyciu Ustawień i ApplicationSettingsBase
Gishu
2

Czasami chcesz pozbyć się tych ustawień przechowywanych w tradycyjnym pliku web.config lub app.config. Chcesz mieć bardziej szczegółową kontrolę nad wdrażaniem wpisów ustawień i oddzielnym projektem danych. Lub wymagane jest, aby umożliwić dodawanie nowych wpisów w czasie wykonywania.

Mogę sobie wyobrazić dwie dobre opcje:

  • Wersja mocno napisana i
  • Wersja obiektowa.

Zaletą mocno wpisanej wersji są mocno wpisane nazwy i wartości ustawień. Nie ma ryzyka mieszania nazw lub typów danych. Wadą jest to, że trzeba zakodować więcej ustawień, których nie można dodać w czasie wykonywania.

W przypadku wersji zorientowanej obiektowej zaletą jest możliwość dodawania nowych ustawień w czasie wykonywania. Ale nie masz mocno wpisanych nazw i wartości. Należy uważać na identyfikatory ciągów. Podczas uzyskiwania wartości należy znać typ danych zapisany wcześniej.

Kod obu w pełni funkcjonalnych implementacji można znaleźć TUTAJ .

użytkownik3130351
źródło
2

Tak, możliwe jest zapisanie konfiguracji - ale w dużej mierze zależy to od wybranego sposobu. Pozwól mi opisać różnice techniczne, abyś mógł zrozumieć dostępne opcje:

Najpierw musisz rozróżnić, czy chcesz używać applicationSettings czy AppSettings w swoim pliku *.exe.config(inaczej App.configw Visual Studio) - istnieją podstawowe różnice, które zostały opisane tutaj .

Oba zapewniają różne sposoby zapisywania zmian:

  • W AppSettings pozwalają odczytywać i zapisywać bezpośrednio w pliku konfiguracyjnym (przez config.Save(ConfigurationSaveMode.Modified);, gdzie config jest zdefiniowany jako config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);).

  • W applicationSettings pozwala na odczyt, ale jeśli piszesz zmian (przez Properties.Settings.Default.Save();) będzie napisany na zasadzie per-user, przechowywane w specjalnym miejscu (np C:\Documents and Settings\USERID\Local Settings\Application Data\FIRMNAME\WindowsFormsTestApplicati_Url_tdq2oylz33rzq00sxhvxucu5edw2oghw\1.0.0.0). Jak wspomniał Hans Passant w swojej odpowiedzi, dzieje się tak dlatego, że użytkownik zwykle ma ograniczone prawa do plików programu i nie może do nich pisać bez wywołania monitu UAC. Wadą jest to, że jeśli dodajesz klucze konfiguracyjne w przyszłości, musisz zsynchronizować je z każdym profilem użytkownika.

Uwaga: Jak wspomniano w pytaniu, istnieje trzecia opcja: jeśli traktujesz plik konfiguracyjny jako dokument XML, możesz go załadować, zmodyfikować i zapisać za pomocą System.Xml.Linq.XDocumentklasy. Nie jest wymagane użycie niestandardowego pliku XML, można odczytać istniejący plik konfiguracyjny; do zapytań o elementy można nawet użyć zapytań Linq. Podałem tutaj przykład , sprawdź funkcję GetApplicationSettingw odpowiedzi.

Jeśli potrzebujesz szyfrowania w celu ochrony swoich wartości, sprawdź odpowiedź.

Matt
źródło
Dziękuję za tę doskonałą odpowiedź.
NoChance
2
@NoChance - Nie ma za co, cieszę się, że mogłem pomóc!
Matt
Miły! W końcu wszystko wymyśliłem 😂😂😂
Momoro
1
@Momoro - dobrze słyszeć! ;-)
Matt
1
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();
    }
}
Paul - Soura Tech LLC
źródło