Làm cách nào để lưu cài đặt ứng dụng trong ứng dụng Windows Forms?


582

Điều tôi muốn đạt được rất đơn giản: Tôi có một ứng dụng Windows Forms (.NET 3.5) sử dụng đường dẫn để đọc thông tin. Đường dẫn này có thể được sửa đổi bởi người dùng, bằng cách sử dụng mẫu tùy chọn tôi cung cấp.

Bây giờ, tôi muốn lưu giá trị đường dẫn vào một tệp để sử dụng sau. Đây sẽ là một trong nhiều cài đặt được lưu vào tệp này. Tập tin này sẽ ngồi trực tiếp trong thư mục ứng dụng.

Tôi hiểu ba tùy chọn có sẵn:

  • Tệp cấu hình cài đặt (appname.exe.config)
  • Đăng ký
  • Tệp XML tùy chỉnh

Tôi đọc rằng tệp cấu hình .NET không lường trước được để lưu các giá trị lại cho nó. Đối với đăng ký, tôi muốn càng xa nó càng tốt.

Điều này có nghĩa là tôi nên sử dụng tệp XML tùy chỉnh để lưu cài đặt cấu hình?

Nếu vậy, tôi muốn xem ví dụ mã về điều đó (C #).

Tôi đã thấy các cuộc thảo luận khác về chủ đề này, nhưng nó vẫn chưa rõ ràng với tôi.


Đây có phải là ứng dụng .NET WinForms không? Nếu vậy, bạn đang phát triển phiên bản .NET nào?
Portman

1
Vâng, đó là một ứng dụng .NET framework phiên bản 3.5 WinForms.
Cung cấp nhiên liệu vào

1
Bạn có cần lưu mật khẩu hoặc giá trị bí mật ? Có thể yêu cầu bất kỳ mã hóa
Kiquenet

Câu trả lời:


593

Nếu bạn làm việc với Visual Studio thì việc cài đặt bền bỉ là khá dễ dàng. Nhấp chuột phải vào dự án trong Solution Explorer và chọn Thuộc tính. Chọn tab Cài đặt và nhấp vào siêu liên kết nếu cài đặt không tồn tại.

Sử dụng tab Cài đặt để tạo cài đặt ứng dụng. Visual Studio tạo các tệp Settings.settingsSettings.Designer.settingscó chứa lớp singleton Settingsđược kế thừa từ ApplicationSinstallBase . Bạn có thể truy cập lớp này từ mã của bạn để đọc / ghi cài đặt ứng dụng:

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

Kỹ thuật này được áp dụng cho cả bảng điều khiển, Windows Forms và các loại dự án khác.

Lưu ý rằng bạn cần đặt thuộc tính phạm vi của cài đặt của mình. Nếu bạn chọn Phạm vi ứng dụng thì Cài đặt.Default. <Thuộc tính của bạn> sẽ ở chế độ chỉ đọc.

Tham khảo: Cách thực hiện: Viết cài đặt người dùng trong thời gian chạy bằng C # - Microsoft Docs


2
Nếu tôi có một giải pháp, điều này sẽ áp dụng cho toàn bộ giải pháp hay cho từng dự án?
franko_camron

8
@Four: Tôi đã có một dự án WinApp .NET 4.0 ở đây và một số chương trình của tôi không đọc được. Settings.Default.SomeProperty = 'value'; Settings.Default.Save();hoạt động như một lá bùa. Hay đó là vì tôi đã có Cài đặt người dùng?
doekman

4
@Four: Khi tôi thay đổi cài đặt từ Phạm vi người dùng sang Phạm vi ứng dụng và lưu tệp, tôi thấy trong mã được tạo, bộ cài đặt biến mất. Điều này cũng xảy ra với hồ sơ khách hàng 4.0 ...
doekman

3
@Four: liên kết tuyệt vời, mặc dù tuyên bố của bạn rằng Settings.Default.Save()không có gì là không chính xác. Như @aku nêu trong câu trả lời, cài đặt phạm vi ứng dụng là chỉ đọc: lưu là không hiệu quả đối với họ. Sử dụng PortableSinstallProvider tùy chỉnh đó để lưu cài đặt phạm vi người dùng vào app.config nằm ở vị trí exe thay vì cài đặt trong thư mục AppData của người dùng. Không, nói chung là không tốt, nhưng tôi sử dụng nó trong quá trình phát triển để sử dụng cùng các cài đặt từ biên dịch đến biên dịch (w / o nó, chúng đi các thư mục người dùng duy nhất mới với mỗi lần biên dịch).
minnow

7
Đến bây giờ, với .NET 3.5, có vẻ như bạn chỉ cần sử dụng Settings.Default.SomeProperty để gán giá trị và nhận được kiểu chữ mạnh mẽ. Ngoài ra, để tiết kiệm thời gian của người khác (tôi mất một chút thời gian để tìm hiểu điều này), bạn cần nhập Properties.Sinstall.Default hoặc thêm bằng YourProjectNameSpace.Sinstall vào đầu tệp của bạn. "Cài đặt" một mình không được xác định / tìm thấy.
eselk

95

Nếu bạn đang dự định lưu vào một tệp trong cùng thư mục với tệp thực thi của mình, thì đây là một giải pháp hay sử dụng định dạng 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;
        }
    }
}

Có, thay đổi DEFAULT_FILENAME thành một đường dẫn tuyệt đối nếu bạn muốn lưu vào thư mục khác. Tôi nghĩ rằng việc lưu tệp vào cùng thư mục với ứng dụng hoặc thư mục con là phổ biến nhất nếu bạn không lưu chúng vào sổ đăng ký.
Trevor

Ồ, có lẽ tùy chọn tốt hơn sẽ là lưu trữ tệp cài đặt trong thư mục appdata của người dùng.
Trevor

1
Không cần thay đổi DEFAULT_FILENAME, chỉ cần gọi settings.Save(theFileToSaveTo); Là tất cả các mũ, DEFAULT_FILENAMEđược coi là một hằng số . Nếu bạn muốn một thuộc tính đọc-ghi, hãy tạo một thuộc tính và đặt hàm tạo DEFAULT_FILENAME. Sau đó, có giá trị đối số mặc định là null, kiểm tra điều này và sử dụng thuộc tính của bạn làm giá trị mặc định. Nó gõ nhiều hơn một chút, nhưng cung cấp cho bạn một giao diện chuẩn hơn.
Jesse Chisholm

10
Bạn sẽ cần tham khảo System.Web.Extensions.dllnếu bạn chưa có.
TEK

9
Tôi đã tạo toàn bộ thư viện dựa trên câu trả lời này với nhiều cải tiến và cung cấp nó trong
nuget

67

Việc đăng ký là không có. Bạn không chắc chắn liệu người dùng sử dụng ứng dụng của bạn, có đủ quyền để ghi vào sổ đăng ký hay không.

Bạn có thể sử dụng app.configtệp để lưu cài đặt cấp ứng dụng (tương tự cho mỗi người dùng sử dụng ứng dụng của bạn).

Tôi sẽ lưu trữ các cài đặt dành riêng cho người dùng trong tệp XML, tệp này sẽ được lưu trong Bộ lưu trữ riêng biệt hoặc trong thư mục SpecialFolder.ApplicationData .

Bên cạnh đó, như từ .NET 2.0, có thể lưu trữ các giá trị trở lại app.configtệp.


8
Tuy nhiên, hãy sử dụng sổ đăng ký nếu bạn muốn cài đặt cho mỗi lần đăng nhập / người dùng.
thenonhacker

19
Đăng ký là không portble
Kb.

10
@thenonhacker: Hoặc sử dụng Môi trường.GetFolderPath (Môi trường. SpecialFolder.ApplicationData)
Kenny Mann

4
Sổ đăng ký người dùng có thể được ghi vào (rất nhiều chương trình ghi thông tin ở đó và quyền của người dùng không bao giờ là vấn đề). Ưu điểm của việc sử dụng sổ đăng ký so với sử dụng cài đặt là nếu bạn có nhiều ứng dụng chia sẻ cùng một thư mục, (giả sử, chương trình thiết lập và chương trình ứng dụng), chúng sẽ không chia sẻ cùng cài đặt.
Kesty

3
Nhược điểm chính của Registry là cách khó để xuất / sao chép cài đặt sang PC khác. Nhưng tôi không đồng ý với "Bạn không chắc người dùng sử dụng ứng dụng của mình, có đủ quyền để ghi vào sổ đăng ký hay không" - Trong HKEY_CURRENT_USER bạn luôn có quyền viết. Nó có thể bị từ chối nhưng hệ thống tập tin cũng có thể không truy cập được đối với người dùng hiện tại (tất cả các thư mục TEMP có thể, v.v.).
i486

20

Các ApplicationSettingslớp không hỗ trợ tiết kiệm cài đặt vào app.config file. Đó là rất nhiều bởi thiết kế; các ứng dụng chạy với tài khoản người dùng được bảo mật đúng cách (nghĩ rằng Vista UAC) không có quyền ghi vào thư mục cài đặt của chương trình.

Bạn có thể chiến đấu với hệ thống với ConfigurationManagerlớp. Nhưng cách giải quyết tầm thường là đi vào trình thiết kế Cài đặt và thay đổi phạm vi cài đặt thành Người dùng. Nếu điều đó gây ra khó khăn (giả sử, cài đặt có liên quan đến mọi người dùng), bạn nên đặt tính năng Tùy chọn của mình trong một chương trình riêng để bạn có thể yêu cầu nhắc nhở nâng cao đặc quyền. Hoặc báo trước bằng cách sử dụng một thiết lập.


Bạn có thể vui lòng mở rộng khi câu cuối cùng của bạn? Yêu cầu độ cao để viết app.config hoặc viết một ứng dụng riêng biệt sẽ đi qua tất cả những người ở nhà của người dùng, tìm kiếm user.config và chỉnh sửa chúng?
CannibalSmith

2
Chương trình riêng biệt yêu cầu một bảng kê khai để yêu cầu độ cao. Google 'asinvoker Yêu cầu quản trị viên' để tìm cú pháp thích hợp. Chỉnh sửa user.config là không thực tế, cũng không cần thiết.
Hans Passant

18

Đối số registry / configureSinstall / XML vẫn có vẻ rất tích cực. Tôi đã sử dụng tất cả, vì công nghệ đã phát triển, nhưng sở thích của tôi dựa trên hệ thống của Threed kết hợp với Lưu trữ biệt lập .

Mẫu sau đây cho phép lưu trữ các đối tượng có tên thuộc tính vào một tệp trong bộ lưu trữ bị cô lập. Nhu la:

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

Các thuộc tính có thể được phục hồi bằng cách sử dụng:

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

Nó chỉ là một mẫu, không gợi ý các thực hành tốt nhất.

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) { }
        }
    }
}

1
Hoặc tốt hơn vẫn là; sử dụng DataContractJsonSerializer
Boczek

16

Tôi muốn chia sẻ một thư viện tôi đã xây dựng cho việc này. Đó là một thư viện nhỏ, nhưng là một cải tiến lớn (IMHO) đối với các tệp .sinstall.

Thư viện được gọi là Jot (GitHub) . Đây là một bài viết cũ của Dự án Code tôi đã viết về nó.

Đây là cách bạn sử dụng nó để theo dõi kích thước và vị trí của cửa sổ:

public MainWindow()
{
    InitializeComponent();

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

Lợi ích so với các tệp .sinstall: Có ít mã hơn đáng kể và nó ít bị lỗi hơn vì bạn chỉ cần đề cập đến mỗi thuộc tính một lần .

Với một tệp cài đặt, bạn cần đề cập đến mỗi thuộc tính năm lần: một lần khi bạn rõ ràng tạo thuộc tính và thêm bốn lần trong mã sao chép các giá trị qua lại.

Lưu trữ, tuần tự hóa, vv là hoàn toàn cấu hình. Khi các đối tượng đích được tạo bởi một bộ chứa IoC , bạn có thể [nối nó] [] để nó tự động áp dụng theo dõi cho tất cả các đối tượng mà nó giải quyết, để tất cả những gì bạn cần làm để duy trì một thuộc tính là có thể theo dõi [Có thể theo dõi] thuộc tính trên đó.

Nó có khả năng cấu hình cao và bạn có thể định cấu hình: - khi dữ liệu được duy trì và áp dụng trên toàn cầu hoặc cho từng đối tượng được theo dõi - cách thức nó được tuần tự hóa - nơi lưu trữ (ví dụ: tệp, cơ sở dữ liệu, trực tuyến, lưu trữ bị cô lập, đăng ký) - các quy tắc có thể hủy áp dụng / lưu trữ dữ liệu cho một tài sản

Tin tôi đi, thư viện là đỉnh cao!


14

Một cách đơn giản là sử dụng một đối tượng dữ liệu cấu hình, lưu nó dưới dạng tệp XML với tên của ứng dụng trong Thư mục cục bộ và khi khởi động đọc lại.

Dưới đây là một ví dụ để lưu trữ vị trí và kích thước của biểu mẫu.

Cấu hình dataobject được gõ mạnh và dễ sử dụng:

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

Một lớp người quản lý để lưu và tải:

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

Bây giờ bạn có thể tạo một cá thể và sử dụng trong các sự kiện tải và đóng biểu mẫu của bạn:

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

Và tệp XML được sản xuất cũng có thể đọc được:

<?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>

1
Tôi có khả năng phát triển rất tốt, nhưng khi tôi triển khai ứng dụng, người dùng trung bình không có quyền truy cập vào c:\program files\my applicationthư mục, vì vậy việc lưu cài đặt sẽ gây ra lỗi. Thay vào đó, tôi đang tìm cách lưu tệp xml trong AppData, nhưng tôi chỉ tự hỏi liệu có cách nào rõ ràng xung quanh vấn đề này không, vì cách tiếp cận này dường như đã có hiệu quả với bạn.
Philip Stratford

@PhilipStratford Vì đây chỉ là một tệp bình thường, bạn có thể lưu nó ở bất cứ đâu. Chỉ cần tìm một nơi có quyền truy cập viết.
Người ăn kiêng Meemken

@PhilipStratford Có thể thư mục AppData là một tùy chọn dành cho bạn, hãy xem C # lấy đường dẫn của% AppData% , như được đề cập bởi diều .
Người ăn kiêng Meemken

Cảm ơn, tôi đã thực hiện điều này, lưu tệp xml trong thư mục AppDate. Tôi chỉ tự hỏi liệu có một cách dễ dàng để lưu nó trong thư mục của ứng dụng theo ví dụ của bạn hay không, vì tôi cho rằng bạn đã làm cho nó hoạt động. Đừng lo lắng, thư mục AppData có lẽ là một vị trí tốt hơn!
Philip Stratford


5

Các tùy chọn khác, thay vì sử dụng tệp XML tùy chỉnh, chúng tôi có thể sử dụng định dạng tệp thân thiện với người dùng hơn: tệp JSON hoặc YAML.

  • Nếu bạn sử dụng .NET 4.0 động, thư viện này thực sự dễ sử dụng (tuần tự hóa, giải tuần tự hóa, hỗ trợ các đối tượng lồng nhau và sắp xếp đầu ra theo ý muốn + hợp nhất nhiều cài đặt thành một) JsonConfig (mức sử dụng tương đương với ApplicationSinstallBase)
  • Đối với thư viện cấu hình .NET YAML ... Tôi chưa tìm thấy thư viện nào dễ sử dụng như JsonConfig

Bạn có thể lưu trữ tệp cài đặt của mình trong nhiều thư mục đặc biệt (cho tất cả người dùng và mỗi người dùng) như được liệt kê ở đây Môi trường. Đặc tính liệt kê và nhiều tệp (chỉ đọc mặc định, cho mỗi vai trò, mỗi người dùng, v.v.)

Nếu bạn chọn sử dụng nhiều cài đặt, bạn có thể hợp nhất các cài đặt đó: Ví dụ: hợp nhất các cài đặt cho mặc định + BasicUser + AdminUser. Bạn có thể sử dụng quy tắc của riêng mình: quy tắc cuối cùng ghi đè giá trị, v.v.


4

"Điều này có nghĩa là tôi nên sử dụng tệp XML tùy chỉnh để lưu cài đặt cấu hình?" Không, không nhất thiết. Chúng tôi sử dụng SharpConfig cho các hoạt động như vậy.

Chẳng hạn, nếu một tập tin cấu hình là như thế

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

Chúng ta có thể lấy các giá trị như thế này

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

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

Nó tương thích với .NET 2.0 trở lên. Chúng tôi có thể tạo các tệp cấu hình một cách nhanh chóng và chúng tôi có thể lưu nó sau này.

Nguồn: http://sharpconfig.net/
GitHub: https://github.com/cemdervis/SharpConfig


3

Theo như tôi có thể nói, .NET không hỗ trợ các cài đặt bền vững bằng cách sử dụng tiện ích cài đặt ứng dụng tích hợp:

Tính năng Cài đặt ứng dụng của Windows Forms giúp dễ dàng tạo, lưu trữ và duy trì tùy chọn người dùng và ứng dụng tùy chỉnh trên máy khách. Với cài đặt ứng dụng Windows Forms, bạn có thể lưu trữ không chỉ dữ liệu ứng dụng, chẳng hạn như chuỗi kết nối cơ sở dữ liệu, mà cả dữ liệu dành riêng cho người dùng, chẳng hạn như tùy chọn ứng dụng của người dùng. Sử dụng Visual Studio hoặc mã được quản lý tùy chỉnh, bạn có thể tạo cài đặt mới, đọc chúng và ghi chúng vào đĩa, liên kết chúng với các thuộc tính trên biểu mẫu của bạn và xác thực dữ liệu cài đặt trước khi tải và lưu. - http://msdn.microsoft.com/en-us/l Library / k4s6c3a0.aspx


2
Không đúng .. xem câu trả lời của aku ở trên. có thể sử dụng Cài đặt và ApplicationSinstallBase
Gishu

2

Đôi khi bạn muốn loại bỏ các cài đặt được lưu trong tệp web.config hoặc app.config truyền thống. Bạn muốn kiểm soát chi tiết hơn đối với việc triển khai các mục cài đặt và thiết kế dữ liệu riêng biệt. Hoặc yêu cầu là cho phép thêm các mục mới trong thời gian chạy.

Tôi có thể tưởng tượng hai lựa chọn tốt:

  • Phiên bản gõ mạnh và
  • Các phiên bản hướng đối tượng.

Ưu điểm của phiên bản gõ mạnh là tên và giá trị cài đặt được gõ mạnh. Không có rủi ro xen kẽ tên hoặc loại dữ liệu. Nhược điểm là nhiều mã cài đặt hơn phải được mã hóa, không thể thêm vào lúc chạy.

Với phiên bản hướng đối tượng, lợi thế là các cài đặt mới có thể được thêm vào khi chạy. Nhưng bạn không có tên và giá trị gõ mạnh. Phải cẩn thận với các định danh chuỗi. Phải biết loại dữ liệu được lưu trước đó khi nhận được một giá trị.

Bạn có thể tìm thấy mã của cả hai triển khai đầy đủ chức năng TẠI ĐÂY .


2

Vâng, có thể lưu cấu hình - nhưng nó phụ thuộc khá nhiều vào cách bạn chọn để làm điều đó. Hãy để tôi mô tả sự khác biệt kỹ thuật để bạn có thể hiểu các tùy chọn bạn có:

Trước tiên, bạn cần phân biệt, cho dù bạn muốn sử dụng applicationSinstall hay AppSinstall trong tệp *.exe.config(hay còn gọi là App.configVisual Studio) - có những khác biệt cơ bản, được mô tả ở đây .

Cả hai đều cung cấp các cách khác nhau để lưu thay đổi:

  • Các AppSettings cho phép bạn đọc và ghi trực tiếp vào tập tin cấu hình (thông qua config.Save(ConfigurationSaveMode.Modified);, trong đó cấu hình được định nghĩa là config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);).

  • Các applicationSettings cho phép đọc, nhưng nếu bạn ghi các thay đổi (thông qua Properties.Settings.Default.Save();) nó sẽ được viết trên một cơ sở cho mỗi người dùng, lưu trữ trong một vị trí đặc biệt (ví dụ C:\Documents and Settings\USERID\Local Settings\Application Data\FIRMNAME\WindowsFormsTestApplicati_Url_tdq2oylz33rzq00sxhvxucu5edw2oghw\1.0.0.0). Như Hans Passant đã đề cập trong câu trả lời của mình, điều này là do người dùng thường bị hạn chế quyền đối với Tệp chương trình và không thể ghi vào nó mà không gọi lời nhắc UAC. Một bất lợi là nếu bạn thêm các khóa cấu hình trong tương lai, bạn cần đồng bộ hóa chúng với mọi hồ sơ người dùng.

Lưu ý: Như đã đề cập trong câu hỏi, có một tùy chọn thứ 3: Nếu bạn coi tệp cấu hình là tài liệu XML, bạn có thể tải, sửa đổi và lưu nó bằng cách sử dụng System.Xml.Linq.XDocumentlớp. Không bắt buộc phải sử dụng tệp XML tùy chỉnh, bạn có thể đọc tệp cấu hình hiện có; để truy vấn các phần tử, bạn thậm chí có thể sử dụng các truy vấn Linq. Tôi đã đưa ra một ví dụ ở đây , kiểm tra chức năng GetApplicationSettingcó trong câu trả lời.

Nếu bạn yêu cầu mã hóa để bảo vệ các giá trị của bạn, hãy xem câu trả lời này .


Cảm ơn bạn cho câu trả lời tuyệt vời này.
NoChance

2
@NoChance - Bạn được chào đón, rất vui vì tôi có thể giúp bạn!
Matt

Đẹp! Cuối cùng cũng tìm ra tất cả
Momoro

1
@Momoro - thật tốt khi nghe! ;-)
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();
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.