Read/Write App.Config File with .NET 2.0
2008-09-27 17:56
495 查看
Introduction
This is my first CodeProject article. I would like to show you the most important changes in the System.Configuration namespace with .NET 2.0. I have looked at my blog referrer statistics and saw about 20 hits/day by Google. Most of them were searching information on how to configure the new Enterprise Library but there are also a significant number of people that seem to seek answers to the following questions:How to read/write to App.Config?
How to store a list of objects in a configfile via the
System.Configurationmechanism?
Reason enough for me to shed more light on the
System.Configurationnamespace. The main changes from .NET 1.0/1.1 in the
System.Configurationnamespace are:
Write to your App.Configfile through the Configurationclass
New configuration model for Windows Forms applications
Store complex objects including object collections in your
App.ConfigFile
It is possible to store Connection Strings in the App.Configfile. See ConnectionSettings which enables you to store your settings on an SQL Server. The Enterprise Library for Sample
SqlConfigurationexercises this by implementing a
SqlConfigurationSourcewhich can store and retrieve a ConfigurationSection
So where to start? I think first I will show you the configfile and explain how you can create it programmatically in your application.
The easiest way to read/write AppSettings
If you want to store only key/value pairs in your App.configfile there is a special section in reserved which allows you to do exactly that. Simply add an<appsettings>section and add your data as key/value pairs of the form
<add key="xxx" value="xxxx" />. That's all to create a new app.configfile with settings in it.
App.Config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="Setting1" value="Very" /> <add key="Setting2" value="Easy" /> </appSettings> </configuration>
The data access API has been changed for this type of setting with .NET 2.0. The "old" one liner
ConfigurationSettings.AppSettingshas been deprecated in favor of
ConfigurationManager.AppSettings. Apart from the naming change you can now also write your application settings. For read only access you can look at the
ShowConfigfunction defined below. Writing the last modification time is demonstrated in the
Mainfunction.
![](http://www.codeproject.com/images/minus.gif)
Collapse
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
namespace AppSettings
{
class Program
{
static void ShowConfig()
{
// For read access you do not need to call OpenExeConfiguraton
foreach(string key in ConfigurationManager.AppSettings)
{
string value = ConfigurationManager.AppSettings[key];
Console.WriteLine("Key: {0}, Value: {1}", key, value);
}
}
static void Main(string[] args)
{
ShowConfig();
// Open App.Configof executable
System.Configuration.Configurationconfig=
ConfigurationManager.OpenExeConfiguration
(ConfigurationUserLevel.None);
// Add an Application Setting.
config.AppSettings.Settings.Add("ModificationDate",
DateTime.Now.ToLongTimeString() + " ");
// Save the changes in App.configfile.
config.Save(ConfigurationSaveMode.Modified);
// Force a reload of a changed section.
ConfigurationManager.RefreshSection("appSettings");
ShowConfig();
}
}
}
Expected Output:
Key: Settings1, Value: Very Key: Setting2, Value: Easy Key: Settings1, Value: Very Key: Setting2, Value: Easy Key: Modification Date, Value: 01:21:03
With this mechanism you can read and update simple key/value pairs within your application without digging any deeper in the
System.Configurationnamespace. The following examples show the other features like the new Windows forms configuration mechanism, create your own configuration section and how you can easily store lists of objects in the App.configfile with the new Enterprise Library helper classes.
Using the MySettings Feature
When developing Windows Forms with VS2005 you get for free a new configuration mechanism. The Windows Forms designers were so nice to create an access class automatically from your configvalues and came up with a consistent model to store application global configfiles in the app.config.exe file and user specific settings within the user profile in user.config. Please note that the Forms configuration model is not available in class library projects since you have no App.configfile for your DLL. When you add a settings file to your class library project you can merge the settings with the App.configfile of your hosting executable. This can be useful if you want to enforce that every application that uses your library can have its own settings inside the App.configfile of the executable. You have the freedom to store your settings wherever you would like to. Any provider can be plugged into your configdata access class by decorating your configuration class with the SettingsProviderAttribute. If none is specified, the LocalFileSettingsProvider is used which relies onSystem.Configuration. This is the reason why you do not need to reference the
System.Configurationassembly in a Windows form, but you see the
System.Configurationassembly loaded in your Windows forms application. You can check it with the debugger in the loaded modules list.
Below is a new Windows Forms project shown which was generated via New->Project->Windows Application. The new configuration features are visible in the Properties folder of your project. There go your resources and the automatically generated strongly typed resource access class with static properties to allow easy and type safe access to your resources. This is similar to the old C programming model with Windows resources. You had an header file with resource ids generated by the resource compiler which spits out a header file which is compiled (compile time checking of the existence of resources) and an object file which is linked into your target. Now you have also compile time checking in .NET if you access your resources via the static properties.
The configuration features surface in the auto generated Settings.settings file and Settings.Designer.cs. To create new configuration values you have full Designer integration within Visual Studio (see picture below). In your code you can read/modify these settings via the generated access class. Inside the visual editor you can choose between two scopes for each of your configuration settings: Application and User. The Application scope defines configuration values which cannot be changed by the user and are the same for all users of this application. User scoped settings on the other hand can be changed/created by, well the users and are stored within their local profile. Application scoped settings cannot be altered when you save your settings. Only the user settings are written to disk during a save operation!
VS 2005 generated Windows Forms application skeleton.
Settings.settings
(Generated by Visual Studio)
<?xml version='1.0' encoding='utf-8'?> <SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="WindowsApplication1.Properties" GeneratedClassName="Settings"> <Profiles /> <Settings> <Setting Name="testSetting" Type="System.String" Scope="User"> <Value Profile="(Default)">Form1</Value> </Setting> </Settings> </SettingsFile>
Settings.Designer.cs
(Generated by Visual Studio using the SettingsSingleFileGenerator as Custom Build Tool)
namespace WindowsApplication1.Properties { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings) (global::System.Configuration.ApplicationSettingsBase.Synchronized( new Settings()))); public static Settings Default { get { return defaultInstance; } } [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("Form1")] public string testSetting { get { return ((string)(this["testSetting"])); } set { this["testSetting"] = value; } } } }
To load your settings programmatically, you only need to do a:
Settings set = Settings.Default;
and access your settings via the property of the returned instance.
string str = set.testSetting;
Wow that was easy. Wasn´t it? Now let's save our changed test setting:
set.testSetting = "test value"; set.Save();
That's pretty much it. To display some of your settings in your form you can use data binding and let your users configure the application font, color, .... User specific settings are stored in %APPDATA%\<AppName>\<AppName><AppConfigName_GUID>\<AssemblyVersion>\user.config. The path to the user configon my machine is e.g. %APPDATA%\WindowsApplication1\WindowsApplication1.exe_Url_x00ebzylso3e0rtwd1pnxkhduwr34pgb\1.0.0.0. This enables you to install a Windows Forms App as Administrator for all users with some global settings in the executable App.configand user specific settings which are stored in the user profile. If your users are in a domain with a roaming profile they will get the same profile and thus the same user settings on every computer they work.
Is this new mechanism compatible with the old one?
Yes it is. Even more: these nice classes do rely heavily on theSystem.Configurationfeatures. Each user/application section is put into its own
ConfigurationSectionGroupCollectionwhich can be accessed programmatically. Every group does contain one or more configuration section/s of the type
ClientSettingsSectionwhich serves as a container for your strongly typed key/value pairs. The following code enumerates all your auto generated settings and prints them out to the Console.
![](http://www.codeproject.com/images/minus.gif)
Collapse
// Get the application configuration file.
System.Configuration.Configurationconfig=
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get the collection of the section groups.
ConfigurationSectionGroupCollection sectionGroups = config.SectionGroups;
// Show the configuration values
ShowSectionGroupCollectionInfo(sectionGroups);
static void ShowSectionGroupCollectionInfo(
ConfigurationSectionGroupCollection sectionGroups)
{
ClientSettingsSectionclientSection;
SettingValueElement value;
foreach(ConfigurationSectionGroup group in sectionGroups)
// Loop over all groups
{
if(!group.IsDeclared)
// Only the ones which are actually defined in app.config
continue;
Console.WriteLine("Group {0}", group.Name);
// get all sections inside group
foreach(ConfigurationSection section in group.Sections)
{
clientSection = section as ClientSettingsSection;
Console.WriteLine("\tSection: {0}", section);
if(clientSection == null)
continue;
foreach(SettingElement set in clientSection.Settings)
{
value = set.Value as SettingValueElement;
// print out value of each section
Console.WriteLine("\t\t{0}: {1}",
set.Name,value.ValueXml.InnerText);
}
}
}
}
How To Read/Write Another App.ConfigFile
To open another App.Configfile, you need to create an instance of"http://msdn2.microsoft.com/en-us/library/system.configuration.execonfigurationfilemap.aspx">ExeConfigurationFileMap. The purpose of this class is not that obvious but we can use it to open another file. Once you have learnt this little trick the rest is easy. Here is a little example that opens a file by specifying it's name, makes some changes to it and writes the changes to disk.
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(); fileMap.ExeConfigFilename = @"ConfigTest.exe.config"; // relative path names possible // Open another configfile Configurationconfig= ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); //read/write from it as usual ConfigurationSection mySection = config.GetSection("mySection"); config.SectionGroups.Clear(); // make changes to it config.Save(ConfigurationSaveMode.Full); // Save changes
The Microsoft Enterprise Library way has a shorthand utility class for this. It is the
FileConfigurationSourcewhich hides those strange things. Tom Hollander has a nice post explaining this already so I will not repeat the same here.
How To Read/Write Serialized Objects
A more advanced way to store our settings is to create our ownConfigurationSection. This makes our configuration values distinguishable from other configuration values inside the App.configfile. It is a little more complicated since you have to write your own class whose content is de/serialized to the App.configfile. I am going to show you at first the configfile and then explain what code you need to write to read/save these settings to your application configuration file.
App.Config(Taken from the Enterprise Library ConfigurationMigration QuickStart Sample)
<configuration> <configSections> <section name="EditorSettings" type="ConfigurationMigrationQuickStart.EditorFontData, ConfigurationMigrationQuickStart, Version=1.1.0.0, Culture=neutral,PublicKeyToken=null"/> </configSections> <EditorSettings name="Verdana" size="24" style="2" /> </configuration>
Most App.configfiles which contain configdata have a
<configSections>element where many
<section>are defined. The name attribute of a section (in this example "
EditorSettings") tells the configsystem that the class
ConfigurationMigrationQuickStart.EditorFontDatais responsible for the ser/deserialization of the node
<EditorSettings>. The
EditorFontDataclass derives from the
"http://msdn2.microsoft.com/en-us/library/x0kca287(en-US,VS.80).aspx">ConfigurationSectionclass and uses the
"http://msdn2.microsoft.com/en-us/library/k92ha214(en-US,VS.80).aspx">ConfigurationPropertyattribute to create a mapping between the properties to de/serialize and the attribute names in names in the App.Configfile.
![](http://www.codeproject.com/images/minus.gif)
Collapse
using System.Text;
using System.Configuration;
public class EditorFontData: ConfigurationSection
{
public EditorFontData()
{
}
[ConfigurationProperty("name")]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("size")]
public float Size
{
get { return (float)this["size"]; }
set { this["size"] = value; }
}
[ConfigurationProperty("style")]
public int Style
{
get { return (int)this["style"]; }
set { this["style"]= value; }
}
}
To access an
EditorFontDatainstance with values from your configfile you only need to call:
EditorFontDataconfigData = ConfigurationManager.GetSection("EditorSettings")as
EditorFontData;
Please note that the
System.Configuration.ConfigurationManagerreturns only objects with read only properties. Subsequent calls to
GetSectionuse the cached instance inside the
ConfigurationManager. This constraint requires you to create every time a new instance for you e.g.
EditorFontDataobject if you want to write to the App.configfile. You even cannot add an object with the same name twice to the
System.Configuration.Configurationobject. Now comes the fun part: To edit an existing App.configfile you have to remove your
configobject and then add a new object instance to the
Configurationobject. Only then the Save will succeed.
EditorFontDataconfigData = new EditorFontData();
configData.Name = "Arial";
configData.Size = 20;
configData.Style = 2;
Configurationconfig=
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.None);
// You need to remove the old settings object before you can replace it
config.Sections.Remove("EditorSettings");
// with an updated one
config.Sections.Add("EditorSettings", configData);
// Write the new configuration data to the XML file
config.Save();
To get your hands on the
System.Configuration.Configurationobject you have to open your App.Configfile. The .NET configmechanism supports setting inheritance from the
Machine.configfrom which all settings are inherited. Next comes the App.Configfile which is selected by the ConfigurationUserLevel.None file.
Points of Interest
There is much more to this topic which can be found at my blog. This includes an SQL Server Import tool to store yourApp.configsettings inside SQL server with the help of the (patched) Microsoft Enterprise Library.
When you use the MySettings Feature and add a settings collection with an auto generated settings class you will receive in the
Appdomain.CurrentDomain.AssemblyResolveevent handler the request for a not existing "
System.XmlSerializers" assembly. This has something to do with the on the fly generated assemblies by
XmlSerializerbut I do not understand why I should know about this. In the handler I had to alter my application logic to skip this not existing assembly. If you consider this a bug you can vote here.
When you receive the error "Cannot add a ConfigurationSection that already belongs to the Configuration." then you did forget to remove the existing section. You cannot alter a section since it is read only. To replace it you must first call remove and then add to set your new one.
History
Released v1.0 on CodeProject which is based on my article at my blog which also dives into more details regarding the Enterprise Library Configurationsystem.License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)About the Author
Alois Kraus![]() | He is working for a multi national company which is a hard and software vendor of medical equipment. Currently he is located in Germany and enjoys living in general. During his search for programming best practices he was awarded by Microsoft with the Patterns and Pratices Champion Award. Although he finds pretty much everything interesting he pays special attention to .NET software development, software architecture and nuclear physics. To complete the picture he likes hiking in the mountains and collecting crystals.
|
相关文章推荐
- Read/Write App.Config File with .NET 2.0
- Read/Write App.config with .NET 2.0/Enterprise Library
- .net 2.0提取app.config中的connectionString
- Read and write excel file with format by pandas and xlwt libraries of python
- Read a Text File with VBA in Excel, and Write the Text to a Spreadsheet
- asp.net 2.0中加密web.config /App.config
- Android App data write as file data with synchronous Demo
- Create, Read, Write, Copy, Move and Delete a Text File using C# and VB.NET
- How To Read and Write BLOB Data by Using ADO.NET with Visual C# .NET
- How to mount partition with ntfs file system and read write access
- Read ConnectionString from web.config in ASP.NET 2.0
- Read and Write compressed data to a binary file using ASP.NET
- asp.net 2.0中加密web.config /App.config
- How to mount partition with ntfs file system and read write access
- How To Read and Write BLOB Data by Using ADO.NET with Visual C# .NET
- Write log file with .net
- 转:Manage Web.config from XML File by using configSource attribute ASP.Net 2.0
- ASP.NET 2.0加密Web.config 配置文件
- ASP.NET 2.0 FileUpload Server Control (转载自codeproject)
- Free ASP.NET 2.0 web hosting with SQL Server Express