首页 / 知识

关于c#:存储.NET应用程序用户设置的最佳方法是什么?

2023-04-13 03:16:00

关于c#:存储.NET应用程序用户设置的最佳方法是什么?

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

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

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

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

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


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

1
2
3
4
5
6
7
// 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();

它会将设置存储在您描述的类似文件夹结构中(使用路径中的版本)。但是,通过简单的电话:

1
Properties.Settings.Default.Upgrade();

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


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

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


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


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

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


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

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

//获取设置值

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

//设置设置值

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

使用:

1
2
3
4
5
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

//你也可以用section name存储,只使用add name section Set(section_name,name,value)和Get(section_name,name,value)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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);
    }
}

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

Ryan Farley说得对。


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

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

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

我知道这有一些安全性权衡,但我正在排序的数据都没有对这个原因至关重要,而且由于应用程序的大小,我没有遇到任何性能问题。


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

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


应用程序用户设置方法

最新内容

相关内容

热门文章

推荐文章

标签云

猜你喜欢