Fue*_*led 561 c# xml configuration-files application-settings winforms
我想要实现的非常简单:我有一个Windows窗体(.NET 3.5)应用程序,它使用一个路径来读取信息.用户可以使用我提供的选项表单修改此路径.
现在,我想将路径值保存到文件中供以后使用.这将是保存到此文件的众多设置之一.该文件将直接位于应用程序文件夹中.
我理解有三种选择:
我读到.NET配置文件没有预见到将值保存回来.至于注册表,我想尽可能远离它.
这是否意味着我应该使用自定义XML文件来保存配置设置?如果是这样,我希望看到代码示例(C#).
我已经看过关于这个问题的其他讨论,但我仍然不清楚.
aku*_*aku 583
如果您使用Visual Studio,那么很容易获得可持久的设置.在Solution Explorer中右键单击项目,选择Properties.选择"设置"选项卡,如果设置不存在,请单击超链接.使用"设置"选项卡创建应用程序设置.Visual Studio创建文件Settings.settings并Settings.Designer.settings包含Settings从ApplicationSettingsBase继承 的单例类.您可以从代码中访问此类以读取/写入应用程序设置:
Properties.Settings.Default["SomeProperty"] = "Some Value";
Properties.Settings.Default.Save(); // Saves settings in application configuration file
Run Code Online (Sandbox Code Playgroud)
此技术适用于控制台,Windows窗体和其他项目类型.
请注意,您需要设置设置的范围属性.如果选择应用程序范围,则Settings.Default.<your property>将是只读的.
Tre*_*vor 91
如果您计划保存到与可执行文件相同的目录中的文件,这是一个使用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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Fre*_*els 66
注册表是禁止的.您不确定使用您的应用程序的用户是否有足够的权限写入注册表.
您可以使用该app.config文件来保存应用程序级设置(对于使用您的应用程序的每个用户都是相同的).
我会将用户特定的设置存储在XML文件中,该文件将保存在Isolated Storage或SpecialFolder.ApplicationData目录中.
接下来,从.NET 2.0开始,可以将值存储回app.config文件.
Han*_*ant 20
本ApplicationSettings类不支持设置保存到app.config文件.这非常依赖于设计,使用正确安全的用户帐户(想想Vista UAC)运行的应用程序没有对程序安装文件夹的写入权限.
您可以与ConfigurationManager班级对抗系统.但是,简单的解决方法是进入"设置"设计器并将设置的范围更改为"用户".如果这会导致困难(例如,设置与每个用户相关),则应将"选项"功能放在单独的程序中,以便可以请求权限提升提示.或放弃使用设置.
Mat*_*att 18
是的,可以保存配置 - 但这很大程度上取决于您选择的保存方式。让我描述一下技术差异,以便您了解您拥有的选项:
首先,您需要区分是否要在您的(也称为Visual Studio 中)文件中使用applicationSettings或AppSettings - 存在根本差异,请参见此处。*.exe.configApp.config
两者都提供了不同的保存更改的方式:
config.Save(ConfigurationSaveMode.Modified);,其中 config 定义为:config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);Properties.Settings.Default.Save();,它将基于每个用户进行写入,并存储在特殊位置(例如C:\Documents and Settings\USERID\Local Settings\Application Data\FIRMNAME\WindowsFormsTestApplicati_Url_tdq2oylz33rzq00sxhvxucu5edw2oghw\1.0.0.0)。正如Hans Passant在他的回答中提到的,这是因为用户通常对程序文件具有有限的权限,并且在不调用 UAC 提示符的情况下无法对其进行写入。缺点是如果您将来要添加配置密钥,则需要将它们与每个用户配置文件同步。但还有其他一些替代选择:
由于 .NET Core(以及 .NET 5 和 6),第三个选项是appsettings.json使用 Microsoft 配置抽象的文件(也是secrets.json存储在用户配置文件中而不是程序集目录中的文件)。但通常 WinForms 不使用它,所以我提及它只是为了完整性。但是,这里有一些如何读取和写入值的参考。或者,您可以使用Newtonsoft JSON 来读取和写入文件appsettings.json,但不限于此:您还可以使用该方法创建自己的 json 文件。
正如问题中提到的,有第四种选择:如果将配置文件视为XML文档,则可以使用System.Xml.Linq.XDocument类加载、修改和保存它。不需要使用自定义的XML文件,可以读取现有的配置文件;对于查询元素,您甚至可以使用 Linq 查询。我在这里给出了一个例子,请查看GetApplicationSetting答案中的函数。
第五个选项是将设置存储在注册表中。此处描述了如何执行此操作。
最后,还有第六个选项:您可以将值存储在环境中(系统环境或您帐户的环境)。在 Windows 设置(Windows 菜单中的齿轮)中,在搜索栏中输入“环境”,然后在其中添加或编辑它们。要阅读它们,请使用
var myValue = Environment.GetEnvironmentVariable("MyVariable");.
请注意,您的应用程序通常需要重新启动才能获取更新的环境设置。
如果您需要加密来保护您的值,请查看此答案。它描述了如何使用 Microsoft 的 DPAPI 来存储加密的值。
如果您想支持自己的文件(无论是 XML 还是 JSON),了解运行的程序集的目录可能会很有用:
var assemblyDLL = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyDirectory = System.IO.Path.GetDirectoryName(assemblyDLL.Location);
Run Code Online (Sandbox Code Playgroud)
您可以使用assemblyDirectory作为存储文件的基本目录。
ana*_*kic 17
我想分享一个我为此而建的图书馆.这是一个很小的库,但对.settings文件有很大改进(恕我直言).
该库名为Jot(GitHub),这是我写的关于它的旧代码项目文章.
以下是您如何使用它来跟踪窗口的大小和位置:
public MainWindow()
{
InitializeComponent();
_stateTracker.Configure(this)
.IdentifyAs("MyMainWindow")
.AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState))
.RegisterPersistTrigger(nameof(Closed))
.Apply();
}
Run Code Online (Sandbox Code Playgroud)
与.settings文件相比的好处:代码要少得多,而且容易出错,因为你只需要提一次每个属性.
使用设置文件,您需要提及五次每个属性:一次是在显式创建属性时,另外四次是在代码中来回复制值.
存储,序列化等是完全可配置的.当目标对象由IOC容器创建时,您可以[挂钩] []以便它自动将跟踪应用于它所解析的所有对象,这样您需要做的就是使属性持久化是一个[Trackable]属性在上面.
它是高度可配置的,您可以配置: - 数据持久化并应用于全局或每个跟踪对象 - 如何序列化 - 存储位置(例如文件,数据库,在线,隔离存储,注册表) - 可以取消应用/持久化的规则财产的数据
相信我,图书馆是一流的!
小智 16
registry/configurationSettings/XML参数似乎仍然非常活跃.随着技术的进步,我已经全部使用了它们,但我最喜欢的是基于Threed的系统与隔离存储相结合.
以下示例允许将名为properties的对象存储到隔离存储中的文件中.如:
AppSettings.Save(myobject, "Prop1,Prop2", "myFile.jsn");
Run Code Online (Sandbox Code Playgroud)
可以使用以下方法恢复属性
AppSettings.Load(myobject, "myFile.jsn");
Run Code Online (Sandbox Code Playgroud)
这只是一个样本,不是最佳实践的暗示.
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) { }
}
}
}
Run Code Online (Sandbox Code Playgroud)
Die*_*ken 12
一种简单的方法是使用配置数据对象,将其保存为XML文件,并在本地文件夹中使用应用程序的名称,并在启动时将其读回.
以下是存储表单位置和大小的示例.
配置数据对象是强类型的并且易于使用:
[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; }
}
}
Run Code Online (Sandbox Code Playgroud)
用于保存和加载的经理类:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以创建一个实例并在表单的加载和关闭事件中使用:
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();
}
Run Code Online (Sandbox Code Playgroud)
生成的XML文件也是可读的:
<?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>
Run Code Online (Sandbox Code Playgroud)
除了使用自定义XML文件以外,我们还可以使用其他更友好的文件格式:JSON或YAML文件。
您可以将设置文件存储在此处列出的多个特殊文件夹(针对所有用户和每个用户)Environment.SpecialFolder枚举和多个文件(默认只读,针对每个角色,针对每个用户等)
如果选择使用多个设置,则可以合并这些设置:例如,合并默认+ BasicUser + AdminUser的设置。您可以使用自己的规则:最后一个覆盖值,依此类推。
“这是否意味着我应该使用自定义 XML 文件来保存配置设置?” 不,不一定。我们使用 SharpConfig 进行此类操作。
例如,如果一个配置文件是这样的
[General]
# a comment
SomeString = Hello World!
SomeInteger = 10 # an inline comment
Run Code Online (Sandbox Code Playgroud)
我们可以检索这样的值
var config = Configuration.LoadFromFile("sample.cfg");
var section = config["General"];
string someString = section["SomeString"].StringValue;
int someInteger = section["SomeInteger"].IntValue;
Run Code Online (Sandbox Code Playgroud)
它与 .NET 2.0 及更高版本兼容。我们可以动态创建配置文件,稍后我们可以保存它。
来源:http : //sharpconfig.net/
GitHub:https : //github.com/cemdervis/SharpConfig
| 归档时间: |
|
| 查看次数: |
430039 次 |
| 最近记录: |