C# 存储 .NET 应用程序的用户设置的最佳方式是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 08:11:36  来源:igfitidea点击:

What is the best way to store user settings for a .NET application?

提问by LeoD

I have a .NET 2.0 Windows Forms application. Where is the best place the store user settings (considering Windows guidelines)?

我有一个 .NET 2.0 Windows 窗体应用程序。商店用户设置的最佳位置在哪里(考虑 Windows 指南)?

Some people pointed to Application.LocalUserAppDataPath. However, that creates a folder structure like:

有人指指点点Application.LocalUserAppDataPath。但是,这会创建一个文件夹结构,例如:

C:\Documents and Settings\user_name\Local Settings\Application Data\company_name\product_name\product_version\

C:\Documents and Settings\user_name\Local Settings\Application Data\company_name\product_name\product_version\

If I release version 1 of my application and store an XML file there, then release version 2, that would change to a different folder, right? I'd prefer to have a single folder, per user, to store settings, regardless of the application version. ----------------------------------------

如果我发布应用程序的第 1 版并在那里存储一个 XML 文件,然后发布第 2 版,那将更改为不同的文件夹,对吗?无论应用程序版本如何,我都希望每个用户都有一个文件夹来存储设置。---------------------------

采纳答案by Ryan Farley

I love using the built-in Application Settings. Then you have built in support for using the settings designer if you want at design-time, or at runtime to use:

我喜欢使用内置的应用程序设置。然后,如果您想在设计时或运行时使用设置设计器,您就内置了对使用设置设计器的支持:

// read setting
string setting1 = (string)Settings.Default["MySetting1"];
// save setting
Settings.Default["MySetting2"] = "My Setting Value";

// you can force a save with
Properties.Settings.Default.Save();

It does store the settings in a similar folder structure as you describe (with the version in the path). However, with a simple call to:

它确实将设置存储在您描述的类似文件夹结构中(路径中包含版本)。但是,通过一个简单的调用:

Properties.Settings.Default.Upgrade(); 

The app will pull all previous versions settings in to save in.

该应用程序将提取所有以前的版本设置以保存。

回答by LeoD

Settings are standard key-value pairs (string-string). I could wrap them in an XML file, if that helps.

设置是标准的键值对(字符串-字符串)。如果有帮助,我可以将它们包装在一个 XML 文件中。

I'd rather use the file system instead of the registry. It seems to be easier to maintain. In support scenarios, if the user needs to manually open/change the settings, that would be easier if it's in the file system.

我宁愿使用文件系统而不是注册表。似乎更容易维护。在支持场景中,如果用户需要手动打开/更改设置,如果它在文件系统中会更容易。

回答by Dillie-O

I'd go down the folder list you posted except for the product version. You don't want the settings reset after an update is released.

我会查看您发布的文件夹列表,但产品版本除外。您不希望在发布更新后重置设置。

I'm actually moving away from the registry for user settings because of the debug/footprint factor. I'm currently only storing a few basic settings (window size, position, version of a data file) in the registry, and I've run into more problems if an update goes bad or a user loses a second monitor and that is where the application was opening to. A few of them are savvy enough to understand regedit, but for the rest they have to do a reinstall, which is quick, but I think they grumble a bit. With the file based version, all I'd have to do is have them open up an XML file in Notepad and make a quick tweak.

由于调试/足迹因素,我实际上正在远离用户设置的注册表。我目前只在注册表中存储一些基本设置(窗口大小、位置、数据文件的版本),如果更新出错或用户丢失第二台显示器,我会遇到更多问题,那就是该应用程序正在开放。他们中的一些人足够精明,可以理解 regedit,但对于其他人,他们必须重新安装,这很快,但我认为他们有点抱怨。对于基于文件的版本,我所要做的就是让他们在记事本中打开一个 XML 文件并进行快速调整。

In addition, I'm looking to make my application runnable off a USB flash drive, and having the settings tied into the file seems much friendlier to that process. I'm sure I can do some code to check/clean the registry, but I think most of us are already tired of the registry clutter that seems to eat up our machines nowadays.

此外,我希望让我的应用程序可以通过 USB 闪存驱动器运行,并且将设置绑定到文件中似乎对该过程更友好。我确信我可以做一些代码来检查/清理注册表,但我认为我们大多数人已经厌倦了如今似乎正在吞噬我们机器的注册表混乱。

I know there are some security tradeoffs to this, but none of the data I'm sorting is that critical to that cause, and I'm not suffering any performance hits due to the size of the application.

我知道这有一些安全性权衡,但我正在排序的数据中没有一个对这个原因至关重要,而且我没有因应用程序的大小而遭受任何性能损失。

回答by Jason Z

One approach that has worked for me in the past has been to create a settings class and use XML serialization to write it to the file system. You could extend this concept by creating a collection of settings objects and serializing it. You would have all of your settings for all users in one place without having to worry about managing the file system.

过去对我有用的一种方法是创建一个设置类并使用 XML 序列化将其写入文件系统。您可以通过创建一组设置对象并将其序列化来扩展此概念。您将所有用户的所有设置都集中在一个地方,而不必担心管理文件系统。

Before anyone gives me any flak for partially re-inventing the wheel, let me say a few things. For one, it is only a few lines of code to serialize and write the file. Secondly, if you have an object that contains your settings, you don't have to make multiple calls to the appSettings object when you load your app. And lastly, it is very easy to add items that represent your applications state, thereby allowing you to resume a long-running task when the application loads next.

在有人批评我部分重新发明轮子之前,让我先说几件事。一方面,只需几行代码即可序列化和写入文件。其次,如果您有一个包含设置的对象,则在加载应用程序时不必多次调用 appSettings 对象。最后,添加代表您的应用程序状态的项目非常容易,从而允许您在下一次加载应用程序时恢复长期运行的任务。

回答by Lars Truijens

Or write your settings in a xml file and save it using Isolated Storage. Depending on the store you use it saves it in the Application Data folder. You can also choose a roaming enabled store which means when the user logs on a different computer the settings move with them.

或者将您的设置写入一个 xml 文件并使用独立存储保存它。根据您使用的商店,它会将其保存在 Application Data 文件夹中。您还可以选择启用漫游的商店,这意味着当用户登录不同的计算机时,设置会随之移动。

回答by Lars Truijens

Isolated storage is primarily used for applications distributed using ClickOnceand are run in a secure sandbox. The base path is decided for you and you won't be able infer it in your code. The path will be something like "\LocalSettings\ApplicationData\IsolatedStorage\ejwnwe.302\kfiwemqi.owx\url.asdaiojwejoieajae....", not all that friendly. Your storage space is also limited.

隔离存储主要用于使用ClickOnce分发并在安全沙箱中运行的应用程序。基本路径是为您决定的,您将无法在代码中推断出它。路径类似于“\LocalSettings\ApplicationData\IsolatedStorage\ejwnwe.302\kfiwemqi.owx\url.asdaiojwejoieajae....”,并不是那么友好。您的存储空间也是有限的。

Ryan Farley has it right.

瑞安法利说得对

回答by Jonathan Wood

.NET applications have a built-in settings mechanism that is easy to use. The problem with it, in my opinion, is that it stores those settings off into a rather obscure directory and end users will not be able to find it. Moreover, just switching from debug to release build changes the location of this directory, meaning that any settings saved in one configuration are lost in the other.

.NET 应用程序具有易于使用的内置设置机制。在我看来,它的问题在于它将这些设置存储在一个相当隐蔽的目录中,最终用户将无法找到它。此外,仅从调试切换到发布版本会更改此目录的位置,这意味着保存在一个配置中的任何设置都将丢失在另一个配置中。

For these and other reasons, I came up with my own settings code for Windows Forms. It's not quite as slick as the one that comes with .NET, but it's more flexible, and I use it all the time.

由于这些和其他原因,我想出了自己的 Windows Forms 设置代码。它不像 .NET 附带的那样圆滑,但它更灵活,我一直在使用它。

回答by vitalinvent

I try some methods to store my settings to simply text file and i found best way:

我尝试了一些方法将我的设置存储到简单的文本文件中,我找到了最好的方法:

file stored in application folder, to usage , settings.txt: (inside settings file approved comments, try //comment)

文件存储在应用程序文件夹中,用于用法,settings.txt:(在设置文件中批准评论,尝试//评论)

//to get settings value

//获取设置值

Settings.Get("name", "Ivan");

//to set settings value

//设置设置值

Settings.Set("name", "John");

using:

使用:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

//you can store also with section name, to use just add name section Set(section_name,name,value) and Get(section_name,name,value)

//您也可以存储部分名称,只需添加名称部分 Set(section_name,name,value) 和 Get(section_name,name,value)

public static class Settings
{
    private static string SECTION =  typeof(Settings).Namespace;//"SETTINGS";
    private static string settingsPath = Application.StartupPath.ToString() + "\settings.txt";
    [DllImport("kernel32")]
    private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
    [DllImport("kernel32")]
    private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
    public static String GetString(String name)
    {
        StringBuilder temp = new StringBuilder(255);
        int i = GetPrivateProfileString(SECTION,name,"",temp,255,settingsPath);
        return temp.ToString();
    }
    public static String Get(String name, String defVal)
    {
        return Get(SECTION,name,defVal);
    }
    public static String Get(string _SECTION, String name, String defVal)
    {
        StringBuilder temp = new StringBuilder(255);
        int i = GetPrivateProfileString(_SECTION, name, "", temp, 255, settingsPath);
        return temp.ToString();
    }
    public static Boolean Get(String name, Boolean defVal)
    {
        return Get(SECTION, name, defVal);
    }
    public static Boolean Get(string _SECTION, String name, Boolean defVal)
    {
        StringBuilder temp = new StringBuilder(255);
        int i = GetPrivateProfileString(_SECTION,name,"",temp,255,settingsPath);
        bool retval=false;
        if (bool.TryParse(temp.ToString(),out retval))
        {
            return retval;
        } else
        {
            return retval;
        }
    }
    public static int Get(String name, int defVal)
    {
        return Get(SECTION, name, defVal);
    }
    public static int Get(string _SECTION, String name, int defVal)
    {
        StringBuilder temp = new StringBuilder(255);
        int i = GetPrivateProfileString(SECTION,name,"",temp,255,settingsPath);
        int retval=0;
        if (int.TryParse(temp.ToString(),out retval))
        {
            return retval;
        } else
        {
            return retval;
        }
    }
    public static void Set(String name, String val)
    {
        Set(SECTION, name,val);
    }
    public static void Set(string _SECTION, String name, String val)
    {
        WritePrivateProfileString(_SECTION, name, val, settingsPath);
    }
    public static void Set(String name, Boolean val)
    {
        Set(SECTION, name, val);
    }
    public static void Set(string _SECTION, String name, Boolean val)
    {
        WritePrivateProfileString(_SECTION, name, val.ToString(), settingsPath);
    }
    public static void Set(String name, int val)
    {
        Set(SECTION, name, val);
    }
    public static void Set(string _SECTION,String name, int val)
    {
        WritePrivateProfileString(SECTION, name, val.ToString(), settingsPath);
    }
}