提问人:LeoD 提问时间:8/26/2008 最后编辑:ɢʀᴜɴᴛLeoD 更新时间:7/20/2017 访问量:49839
存储 .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 数据\company_name\product_name\product_version\
如果我发布应用程序的版本 1 并在那里存储一个 XML 文件,然后发布版本 2,这将更改为不同的文件夹,对吗?我更希望每个用户都有一个文件夹来存储设置,而不管应用程序版本如何。
答:
设置是标准键值对(字符串-字符串)。如果有帮助,我可以将它们包装在XML文件中。
我宁愿使用文件系统而不是注册表。它似乎更容易维护。在支持方案中,如果用户需要手动打开/更改设置,如果它位于文件系统中,那会更容易。
我会查看您发布的文件夹列表,但产品版本除外。您不希望在发布更新后重置设置。
由于调试/占用空间因素,我实际上正在远离用户设置的注册表。我目前只在注册表中存储了一些基本设置(窗口大小、位置、数据文件的版本),如果更新出错或用户丢失了第二台显示器,我会遇到更多问题,这就是应用程序打开的地方。他们中的一些人足够精明,可以理解regedit,但对于其余的人,他们必须重新安装,这很快,但我认为他们有点抱怨。对于基于文件的版本,我所要做的就是让他们在记事本中打开一个 XML 文件并进行快速调整。
此外,我希望使我的应用程序可以在 USB 闪存驱动器上运行,并且将设置绑定到文件中似乎对该过程更友好。我确信我可以做一些代码来检查/清理注册表,但我认为我们大多数人已经厌倦了现在似乎吞噬我们机器的注册表混乱。
我知道这有一些安全权衡,但我所排序的数据中没有一个对这个原因那么重要,而且我不会因为应用程序的大小而遭受任何性能影响。
我喜欢使用内置的应用程序设置。然后,如果希望在设计时或运行时使用设置设计器,则已内置了对使用设置设计器的支持:
// 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();
该应用程序将提取所有以前版本的设置以保存。
评论
Settings.Default
NSUserDefaults
Properties.Settings.Default.Save();
过去对我有用的一种方法是创建一个设置类,并使用 XML 序列化将其写入文件系统。可以通过创建设置对象的集合并对其进行序列化来扩展此概念。您可以将所有用户的所有设置集中在一个地方,而不必担心管理文件系统。
在有人指责我部分重新发明轮子之前,让我说几件事。首先,只需几行代码即可序列化和写入文件。其次,如果你有一个包含设置的对象,则在加载应用时不必对 appSettings 对象进行多次调用。最后,添加表示应用程序状态的项目非常容易,从而允许您在应用程序下次加载时恢复长时间运行的任务。
评论
或者将设置写入 xml 文件,并使用独立存储进行保存。根据您使用的存储,它会将其保存在 Application Data 文件夹中。您还可以选择启用漫游的应用商店,这意味着当用户登录到其他计算机时,设置会随之移动。
独立存储主要用于使用 ClickOnce 分发的应用程序,并在安全沙盒中运行。基本路径是为您决定的,您将无法在代码中推断它。路径类似于“\LocalSettings\ApplicationData\IsolatedStorage\ejwnwe.302\kfiwemqi.owx\url.asdaiojwejoieajae....”,不是那么友好。您的存储空间也是有限的。
.NET 应用程序具有易于使用的内置设置机制。在我看来,它的问题在于它将这些设置存储到一个相当晦涩的目录中,最终用户将无法找到它。此外,只需从调试切换到发布版本,就会更改此目录的位置,这意味着保存在一个配置中的任何设置都会在另一个配置中丢失。
出于这些原因和其他原因,我为 Windows 窗体设计了自己的设置代码。它不像 .NET 附带的那么流畅,但它更灵活,我一直在使用它。
我尝试了一些方法将我的设置存储为简单的文本文件,我找到了最好的方法:
存储在应用程序文件夹中的文件,以使用,设置.txt: (在设置文件批准的注释中,尝试 //comment)
获取设置值
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);
}
}
上一个:.NET 多维数组打印
评论