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

时间:2008-08-25 16:43:07

标签: c# .net

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

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

  

C:\ Documents and Settings \ user_name \ Local Settings \ Application   数据\ COMPANY_NAME \ PRODUCT_NAME \ PRODUCT_VERSION \

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

8 个答案:

答案 0 :(得分:79)

我喜欢使用内置的Application Settings。然后,如果您想在设计时或运行时使用设置设计器,则内置支持:

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

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

Properties.Settings.Default.Upgrade(); 

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

答案 1 :(得分:8)

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

出于这些和其他原因,我想出了my own settings code for Windows Forms。它不像.NET附带的那样灵巧,但它更灵活,我一直都在使用它。

答案 2 :(得分:5)

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

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

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

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

//获取设置值

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

//设置设置值

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

使用:

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

//你也可以存储部分名称,只使用添加名称部分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);
    }
}

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

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

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

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

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

答案 7 :(得分:0)

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

Ryan Farley has it right