我想要实现的目标非常简单:我有一个 Windows 窗体(.NET 3.5)应用程序,它使用路径来读取信息。 用户可以使用我提供的选项表单来修改此路径。
现在,我想将路径值保存到文件中以供以后使用。 这将是保存到该文件的众多设置之一。 该文件将直接位于应用程序文件夹中。
据我所知,可以使用三个选项:
- ConfigurationSettings 文件 (appname.exe.config)
- 注册表
- 自定义 XML 文件
我读到,.NET 配置文件预计不会将值保存回其中。 至于注册表,我想尽可能远离它。
这是否意味着我应该使用自定义 XML 文件来保存配置设置?
如果是这样,我想看看它的代码示例(C#)。
我看过其他关于这个主题的讨论,但我仍然不清楚。
What I want to achieve is very simple: I have a Windows Forms (.NET 3.5) application that uses a path for reading information. This path can be modified by the user, by using the options form I provide.
Now, I want to save the path value to a file for later use. This would be one of the many settings saved to this file. This file would sit directly in the application folder.
I understand three options are available:
- ConfigurationSettings file (appname.exe.config)
- Registry
- Custom XML file
I read that the .NET configuration file is not foreseen for saving values back to it. As for the registry, I would like to get as far away from it as possible.
Does this mean that I should use a custom XML file to save configuration settings?
If so, I would like to see code example of that (C#).
I have seen other discussions on this subject, but it is still not clear to me.
发布评论
评论(14)
如果您使用 Visual Studio,则很容易获得持久设置。 右键单击“解决方案资源管理器”中的项目并选择“属性”。 选择“设置”选项卡,如果设置不存在,则单击超链接。
使用“设置”选项卡创建应用程序设置。 Visual Studio 创建文件
Settings.settings
和Settings.Designer.settings
,其中包含继承自 ApplicationSettingsBase。 您可以从代码中访问此类以读取/写入应用程序设置:此技术适用于控制台、Windows 窗体和其他项目类型。
请注意,您需要设置设置的范围属性。 如果您选择“应用程序范围”,则选择“Settings.Default”。<您的属性> 将是只读的。
参考:如何:使用 C# 在运行时编写用户设置 - Microsoft Docs
If you work with Visual Studio then it is pretty easy to get persistable settings. Right click on the project in Solution Explorer and choose Properties. Select the Settings tab and click on the hyperlink if settings doesn't exist.
Use the Settings tab to create application settings. Visual Studio creates the files
Settings.settings
andSettings.Designer.settings
that contain the singleton classSettings
inherited from ApplicationSettingsBase. You can access this class from your code to read/write application settings:This technique is applicable both for console, Windows Forms, and other project types.
Note that you need to set the scope property of your settings. If you select Application scope then Settings.Default.<your property> will be read-only.
Reference: How To: Write User Settings at Run Time with C# - Microsoft Docs
如果您计划将文件保存到与可执行文件相同的目录中,这里有一个很好的解决方案,它使用 JSON格式:
If you are planning on saving to a file within the same directory as your executable, here's a nice solution that uses the JSON format:
注册表是不行的。 您不确定使用您的应用程序的用户是否有足够的权限写入注册表。
您可以使用
app.config
文件保存应用程序级别的设置(对于使用您的应用程序的每个用户来说都是相同的)。我会将用户特定的设置存储在 XML 文件中,该文件将保存在 独立存储或SpecialFolder.ApplicationData< /a> 目录。
除此之外,从 .NET 2.0 开始,可以将值存储回
app.config
文件。The registry is a no-go. You're not sure whether the user which uses your application, has sufficient rights to write to the registry.
You can use the
app.config
file to save application-level settings (that are the same for each user who uses your application).I would store user-specific settings in an XML file, which would be saved in Isolated Storage or in the SpecialFolder.ApplicationData directory.
Next to that, as from .NET 2.0, it is possible to store values back to the
app.config
file.ApplicationSettings
类不支持将设置保存到 app.config 文件中。 这很大程度上是设计使然。 使用正确保护的用户帐户(例如 Vista UAC)运行的应用程序没有对该程序的安装文件夹的写入权限。您可以使用
ConfigurationManager
类来对抗系统。 但简单的解决方法是进入“设置”设计器并将设置的范围更改为“用户”。 如果这会导致困难(例如,该设置与每个用户相关),您应该将“选项”功能放在单独的程序中,以便可以请求权限提升提示。 或者放弃使用某个设置。The
ApplicationSettings
class doesn't support saving settings to the app.config file. That's very much by design; applications that run with a properly secured user account (think Vista UAC) do not have write access to the program's installation folder.You can fight the system with the
ConfigurationManager
class. But the trivial workaround is to go into the Settings designer and change the setting's scope to User. If that causes hardships (say, the setting is relevant to every user), you should put your Options feature in a separate program so you can ask for the privilege elevation prompt. Or forego using a setting.我想分享我为此构建的库。 这是一个很小的库,但相对于 .settings 文件来说是一个很大的改进(恕我直言)。
该库名为 Jot (GitHub)。 这是我写的一篇旧的代码项目文章。
以下是如何使用它来跟踪窗口的大小和位置:
与 .settings 文件相比的优点: 代码显着减少,并且更不容易出错,因为您只需要每个属性一次提及。
对于设置文件,您需要提及每个属性五次次:在显式创建属性时提及一次,在来回复制值的代码中另外提及四次。
存储、序列化等是完全可配置的。 当目标对象由 IoC 容器创建时,您可以[将其挂起][]这样它就会自动将跟踪应用于它解析的所有对象,因此要使属性持久化,您所需要做的就是在其上添加 [Trackable] 属性。
它具有高度可配置性,您可以配置:
- 当数据被全局或每个跟踪对象保存和应用时
- 它是如何序列化的
- 存储位置(例如文件、数据库、在线、独立存储、注册表)
- 可以取消应用/保留属性数据的规则
相信我,该库是一流的!
I wanted to share a library I've built for this. It's a tiny library, but a big improvement (IMHO) over .settings files.
The library is called Jot (GitHub). Here is an old The Code Project article I wrote about it.
Here's how you'd use it to keep track of a window's size and location:
The benefit compared to .settings files: There's considerably less code, and it's a lot less error-prone since you only need to mention each property once.
With a settings files you need to mention each property five times: once when you explicitly create the property and an additional four times in the code that copies the values back and forth.
Storage, serialization, etc. are completely configurable. When the target objects are created by an IoC container, you can [hook it up][] so that it applies tracking automatically to all objects it resolves, so that all you need to do to make a property persistent is slap a [Trackable] attribute on it.
It's highly configurable, and you can configure:
- when data is persisted and applied globally or for each tracked object
- how it's serialized
- where it's stored (e.g. file, database, online, isolated storage, registry)
- rules that can cancel applying/persisting data for a property
Trust me, the library is top notch!
是的,可以保存配置 - 但这很大程度上取决于您选择的方式。 让我描述一下技术差异,以便您了解您拥有的选项:
首先,您需要区分您是想在
中使用 applicationSettings 还是 AppSettings* .exe.config
(在 Visual Studio 中又名App.config
)文件 - 存在根本差异, 此处进行了描述。两者都提供了不同的保存更改的方式:
config.Save(ConfigurationSaveMode.Modified);
直接读取和写入配置文件,其中config定义为:< br>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< /code>
答案中有。
第五个选项是将设置存储在注册表中。描述了如何执行此操作这里。
最后,还有一个第六个选项:您可以在环境(系统环境或您帐户的环境)中存储值。 在 Windows 设置(Windows 菜单中的齿轮)中,在搜索栏中输入“环境”,然后在其中添加或编辑它们。 要读取它们,请使用
var myValue = Environment.GetEnvironmentVariable("MyVariable");
。请注意,您的应用程序通常需要重新启动才能获取更新的环境设置。 环境变量不仅限于 Windows,在 Docker 容器中也非常有用。 Microsoft Azure 还可以通过环境变量传递存储在 Azure 中的值。
如果您需要加密来保护您的值,请查看此回答。 它描述了如何使用 Microsoft 的 DPAPI 来存储加密的值。
如果您想支持自己的文件(无论是 XML 还是 JSON),那么了解正在运行的程序集的目录可能会很有用:
您可以使用 assemblyDirectory 作为存储文件的基本目录。
Yes, it is possible to save the configuration - but it pretty much depends on the way you choose to do it. Let me describe the technical differences so you can understand the options you have:
First, you need to distinguish, whether you want to use applicationSettings or AppSettings in your
*.exe.config
(akaApp.config
in Visual Studio) file - there are fundamental differences, being described here.Both provide different ways of saving changes:
config.Save(ConfigurationSaveMode.Modified);
, where config is defined as:config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
Properties.Settings.Default.Save();
) it will be written on a per-user basis, stored in a special place (e.g.C:\Documents and Settings\USERID\Local Settings\Application Data\FIRMNAME\WindowsFormsTestApplicati_Url_tdq2oylz33rzq00sxhvxucu5edw2oghw\1.0.0.0
). As Hans Passant mentioned in his answer, this is because a user usually has restricted rights to Program Files and cannot write to it without invoking the UAC prompt. A disadvantage is if you're adding configuration keys in the future you need to synchronize them with every user profile.But there are a couple of other alternative options:
Since .NET Core (and .NET 5 and 6) a 3rd option is the
appsettings.json
file which uses Microsoft's configuration abstraction (and also thesecrets.json
file which is stored in your user profile rather than in the assemblies directories). But usually WinForms isn't using it, so I am mentioning it just for completeness. However, here are some references how to read and write the values. Alternatively you can use Newtonsoft JSON to read and write theappsettings.json
file, but it is not limited to that: you can also create your own json files with that method.As mentioned in the question, there is a 4th option: If you treat the configuration file as XML document, you can load, modify and save it by using the
System.Xml.Linq.XDocument
class. It is not required to use a custom XML file, you can read the existing config file; for querying elements, you can even use Linq queries. I have given an example here, check out the functionGetApplicationSetting
there in the answer.A 5th option is to store settings in the registry. How you can do it is described here.
Last not least, there is a 6th option: You can store values in the environment (system environment or environment of your account). In Windows settings (the cogwheel in the Windows menu), type in "environment" in the search bar and add or edit them there. To read them, use
var myValue = Environment.GetEnvironmentVariable("MyVariable");
.Note that your application usually needs to be restarted to get the updated environment settings. Environment variables are not limited to Windows, but quite useful for example in Docker containers as well. And Microsoft Azure can also pass on values stored in Azure via environment variables.
If you require encryption to protect your values, check out this answer. It describes how to use Microsoft's DPAPI to store values encrypted.
And if you want to support your own files, whether XML or JSON, it might be useful to know the directory of the assembly running:
You can use
assemblyDirectory
as base directory to store your files.registry/configurationSettings/XML 参数似乎仍然非常活跃。 随着技术的进步,我已经使用了所有这些,但我最喜欢的是基于 Threed 系统 与 结合隔离存储。
以下示例允许将名为属性的对象存储到独立存储中的文件中。 例如:
可以使用以下方式恢复属性:
这只是一个示例,并不暗示最佳实践。
The registry/configurationSettings/XML argument still seems very active. I've used them all, as the technology has progressed, but my favourite is based on Threed's system combined with Isolated Storage.
The following sample allows storage of an objects named properties to a file in isolated storage. Such as:
Properties may be recovered using:
It is just a sample, not suggestive of best practices.
一种简单的方法是使用配置数据对象,将其保存为 XML 文件,并在本地文件夹中使用应用程序的名称,然后在启动时将其读回。
这是存储表单的位置和大小的示例。
配置数据对象是强类型的并且易于使用:
用于保存和加载的管理器类:
现在您可以创建一个实例并在表单的加载和关闭事件中使用:
并且生成的 XML 文件也是可读的:
A simple way is to use a configuration data object, save it as an XML file with the name of the application in the local Folder and on startup read it back.
Here is an example to store the position and size of a form.
The configuration dataobject is strongly typed and easy to use:
A manager class for saving and loading:
Now you can create an instance and use in your form's load and close events:
And the produced XML file is also readable:
“这是否意味着我应该使用自定义 XML 文件来保存配置设置?” 不,不一定。 我们使用 SharpConfig 来进行此类操作。
例如,如果配置文件是这样的,
我们可以检索这样的值
它与.NET 2.0及更高版本兼容。 我们可以即时创建配置文件,并可以稍后保存。
来源:http://sharpconfig.net/
GitHub:https://github.com/cemdervis/SharpConfig
"Does this mean that I should use a custom XML file to save configuration settings?" No, not necessarily. We use SharpConfig for such operations.
For instance, if a configuration file is like that
We can retrieve values like this
It is compatible with .NET 2.0 and higher. We can create configuration files on the fly and we can save it later.
Source: http://sharpconfig.net/
GitHub: https://github.com/cemdervis/SharpConfig
我不喜欢使用
web.config
或app.config
的建议解决方案。 尝试阅读您自己的 XML。 看看XML 设置文件 – 不再有 web.config。I don't like the proposed solution of using
web.config
orapp.config
. Try reading your own XML. Have a look at XML Settings Files – No more web.config.其他选项,我们可以使用更用户友好的文件格式:JSON 或 YAML 文件,而不是使用自定义 XML 文件。
(序列化、反序列化、嵌套对象支持和排序输出
如您所愿+将多个设置合并为一个) JsonConfig (用法相当于ApplicationSettingsBase)
易于使用,如 JsonConfig
您可以将设置文件存储在多个特殊文件夹中(针对所有用户和每个用户),如此处所列 Environment.SpecialFolder 枚举 和多个文件(默认只读、每个角色、每个用户等)
%AppData%
如果您选择使用多个设置,则可以合并这些设置:例如,合并 default + BasicUser + AdminUser 的设置。 您可以使用自己的规则:最后一个规则会覆盖该值,等等。
Other options, instead of using a custom XML file, we can use a more user friendly file format: JSON or YAML file.
(serialize, deserialize, nested objects support and ordering output
as you wish + merging multiple settings to one) JsonConfig (usage is equivalent to ApplicationSettingsBase)
easy to use as JsonConfig
You can store your settings file in multiple special folders (for all users and per user) as listed here Environment.SpecialFolder Enumeration and multiple files (default read only, per role, per user, etc.)
%AppData%
If you choose to use multiple settings, you can merge those settings: For example, merging settings for default + BasicUser + AdminUser. You can use your own rules: the last one overrides the value, etc.
据我所知,.NET 确实支持使用内置应用程序设置工具来保存设置:
As far as I can tell, .NET does support persisting settings using the built-in application settings facility:
有时您想删除保留在传统 web.config 或 app.config 文件中的那些设置。 您希望对设置条目的部署和分离的数据设计进行更细粒度的控制。 或者要求是能够在运行时添加新条目。
我可以想象两个不错的选择:
强类型版本的优点是强类型设置名称和值。 不存在混合名称或数据类型的风险。 缺点是需要编写更多设置,无法在运行时添加。
面向对象版本的优点是可以在运行时添加新设置。 但是您没有强类型的名称和值。 必须小心字符串标识符。 获取值时必须知道之前保存的数据类型。
您可以在此处找到这两个功能齐全的实现的代码。
Sometimes you want to get rid of those settings kept in the traditional web.config or app.config file. You want more fine grained control over the deployment of your settings entries and separated data design. Or the requirement is to enable adding new entries at runtime.
I can imagine two good options:
The advantage of the strongly typed version are the strongly typed settings names and values. There is no risk of intermixing names or data types. The disadvantage is that more settings have to be coded, cannot be added at runtime.
With the object oriented version the advantage is that new settings can be added at runtime. But you do not have strongly typed names and values. Must be careful with string identifiers. Must know data type saved earlier when getting a value.
You can find the code of both fully functional implementations HERE.