Click here to Skip to main content
15,898,134 members
Articles / Web Development / ASP.NET
Article

Application Settings the .NET way. INI, Registry, or XML

Rate me:
Please Sign up or sign in to vote.
4.61/5 (92 votes)
27 Oct 2004BSD4 min read 351.1K   3.6K   144   105
In this article, I’ll explain how you can easily store and retrieve your application settings with just a few lines of code

Introduction

INI files and the registry are generally things of the past for .NET applications. But what to use? XML seems appropriate, but one look at System.XML is enough to scare most developers off, especially just to store a few fields. Fortunately, there is a very easy way in .NET to solve this, but one that is usually not seen by developers. In this article, I’ll explain how you can easily store and retrieve your application settings with just a few lines of code.

History

In Windows 3.1, developers used INI files to store settings. In general, they worked pretty well for simple settings, but were not appropriate for more complex data. INI files also did not account for multiple users, and thus Microsoft invented the registry.

Along came the registry with Win32. The registry was fast, hierarchical, multi user, and allowed storage of typed data. But unfortunately, the registry was a central system component and was not contained as part of the application install.

Next, XML became popular. XML offers fast, hierarchical storage of typed data. However, XML is so flexible that for most users doing anything simple is quite an undertaking. Fortunately, there are easier ways than using System.XML and handling everything yourself.

Old Ways

Many users have simply resorted to using INI files or the registry. INI files are not supported in .NET. To use INI files, a developer must call the Win32 API directly, or use some prepared classes on the Internet that use the Win32 API. For the registry, classes are available in Microsoft.Win32. XML however is portable and can be easily edited by end users if necessary.

How

The secret to painless XML settings files is to use a typed DataSet. A typed DataSet is actually an in memory dataset for working with ADO.NET, but they have many other uses as well. To add a typed DataSet to your application, right click on the project in the Solution Explorer, and select Add New Item. Now select DataSet, and give the dataset a name.

Image 1

Now, we have a blank DataSet in our project. For the purposes of a demo, I have created a main form already that looks like this.

Image 2

I have chosen these for the demo as they give us three types of data to store, a string, an integer, and a Boolean. Now, let’s design our DataSet around these.

Open the Solution Explorer and find the newly created DataSet.

Image 3

When you double click on Settings.xsd, you will see a designer like this:

Image 4

This is a blank DataSet. A DataSet can contain several tables, but for this demo, we will add just one. Open the toolbox, and you will see different items than you normally see in a WinForms or a WebForms application.

Image 5

There are a lot of items in the toolbox related to DataSets, but for the needs of this article, we only need Element. Double click on Element to add one to the DataSet. The DataSet should now look like this:

Image 6

The Element type corresponds to a DataTable. Let’s name it Main (change the highlighted text above to Main). Now, let’s enter the fields that we want to store. The element should look like this when finished:

Image 7

Visual Studio will now take this DataSet and make a set of classes for us that we can use. So now, let’s take a look at the Load and Save buttons on the main form. These events make use of ConfigPathname, this is a field that is predefined in the demo. ConfigPathname just holds the path and filename of the settings file.

C#

C#
private void butnSave_Click(object sender, System.EventArgs e) {
    Settings xDS = new Settings();
    Settings.MainRow xRow = xDS.Main.NewMainRow();
    xRow.Username = textUsername.Text.Trim();
    xRow.PIN = int.Parse(textPIN.Text.Trim());
    xRow.Admin = chckAdmin.Checked;
    xDS.Main.AddMainRow(xRow);
    xDS.WriteXml(ConfigPathname, System.Data.XmlWriteMode.IgnoreSchema);
}

private void butnLoad_Click(object sender, System.EventArgs e) {
    if (new FileInfo(ConfigPathname).Exists) {
        Settings xDS = new Settings();
        xDS.ReadXml(ConfigPathname, System.Data.XmlReadMode.IgnoreSchema);
        if (xDS.Main.Rows.Count > 0) {
            Settings.MainRow xRow = xDS.Main[0];
            if (!xRow.IsUsernameNull()) {
                textUsername.Text = xRow.Username;
            }
            if (!xRow.IsPINNull()) {
                textPIN.Text = xRow.PIN.ToString();
            }
            if (!xRow.IsAdminNull()) {
                chckAdmin.Checked = xRow.Admin;
            }
        }
    }
}

Visual Basic.NET

VB.NET
Private Sub butnSave_Click(ByVal sender As System.Object, 
ByVal e As System.EventArgs) Handles butnSave.Click
  Dim xDS As New Settings
  Dim xRow As Settings.MainRow
  xRow = xDS.Main.NewMainRow
  xRow.Username = textUsername.Text.Trim()
  xRow.PIN = Int32.Parse(textPIN.Text.Trim())
  xRow.Admin = chckAdmin.Checked
  xDS.Main.AddMainRow(xRow)
  xDS.WriteXml(ConfigPathname, System.Data.XmlWriteMode.IgnoreSchema)
End Sub

Private Sub butnLoad_Click(ByVal sender As System.Object, 
ByVal e As System.EventArgs) Handles butnLoad.Click
  If New FileInfo(ConfigPathname).Exists Then
    Dim xDS As New Settings
    Dim xRow As Settings.MainRow
    xDS.ReadXml(ConfigPathname, System.Data.XmlReadMode.IgnoreSchema)
    If xDS.Main.Rows.Count > 0 Then
      xRow = xDS.Main.Rows.Item(0)
      If Not xRow.IsUsernameNull() Then
        textUsername.Text = xRow.Username
      End If
      If Not xRow.IsPINNull() Then
        textPIN.Text = xRow.PIN.ToString()
      End If
      If Not xRow.IsAdminNull() Then
        chckAdmin.Checked = xRow.Admin
      End If
    End If
  End If
End Sub

When loading the DataSet back, it is necessary to check each field for null. In our demo, they would never be null, but if you later add fields and your application tries to load a file that was saved with an older version, fields could be null. End users might also directly edit your settings files. Accessing a field while it is null will generate an exception.

If you run the demo, you can enter some test values and then click Save.

Image 8

After clicking Save, the demo will create a .settings file in the same directory as the .exe. Normally, this is bin/debug/SettingsDemo.exe.Settings. If you open this file, you will see it is a standard XML file and can easily be edited.

XML
<?xml version="1.0" standalone="yes"?>
<Settings xmlns="http://tempuri.org/Settings.xsd">
  <Main>
    <Username>Kudzu</Username>
    <PIN>1234</PIN>
    <Admin>true</Admin>
  </Main>
</Settings>

Now, if you run the application again, you can click the Load button to load these settings.

In this demo, we only stored one row in the DataTable. But DataTables can contain multiple rows, and a DataSet can even contain multiple related or unrelated DataTables.

Conclusion

XML files are a widespread standard that allows easy storage of structured typed data. Use of XML files allows easy editing by end users, and even by other software. Using typed DataSets, you can easily store your settings in XML files.

License

This article, along with any associated source code and files, is licensed under The BSD License


Written By
Cyprus Cyprus
Chad Z. Hower, a.k.a. Kudzu
"Programming is an art form that fights back"

I am a former Microsoft Regional DPE (MEA) covering 85 countries, former Microsoft Regional Director, and 10 Year Microsoft MVP.

I have lived in Bulgaria, Canada, Cyprus, Switzerland, France, Jordan, Russia, Turkey, The Caribbean, and USA.

Creator of Indy, IntraWeb, COSMOS, X#, CrossTalk, and more.

Comments and Discussions

 
GeneralRe: An awkward solution Pin
geneu20-Oct-04 23:07
geneu20-Oct-04 23:07 
GeneralI am losing you... Pin
mirano25-Oct-04 6:27
mirano25-Oct-04 6:27 
GeneralRe: I am losing you... Pin
Chad Z. Hower aka Kudzu25-Oct-04 8:32
Chad Z. Hower aka Kudzu25-Oct-04 8:32 
GeneralRe: An awkward solution Pin
Chad Z. Hower aka Kudzu21-Oct-04 10:42
Chad Z. Hower aka Kudzu21-Oct-04 10:42 
GeneralRe: An awkward solution Pin
Chad Z. Hower aka Kudzu22-Oct-04 3:31
Chad Z. Hower aka Kudzu22-Oct-04 3:31 
GeneralRe: An awkward solution Pin
Yuli23-Oct-04 4:05
Yuli23-Oct-04 4:05 
GeneralRe: An awkward solution Pin
kevinferron12324-Oct-04 16:48
kevinferron12324-Oct-04 16:48 
GeneralRe: An awkward solution Pin
Chad Z. Hower aka Kudzu25-Oct-04 3:03
Chad Z. Hower aka Kudzu25-Oct-04 3:03 
phool_kevin wrote:
Um this is a horrible article, and a horrible coversation. Chad, please don't write any more articles until you take the time to understand what you're even writing about.

A small portion of the users on this site constantly amaze me with not only their ignorance, but their rudeness. Its one thing when someone does not understand something, but its quite amazing when they do not understand something yet are so adamant about their point of view that they resort to insults, and are still incorrect.

phool_kevin wrote:
For the readers out there, the appropiate way to store configuration settings is with keys in your app.config, and if need be, custom elements.

You are wrong on several points.

1) If this is the case - why is the ConfigurationSettings class read only? Please post some sample code to write to the app.config without resorting to modifying the file in raw mode.

2) Why does CofnigurationSettings only support basic text values, that is unless you write a complete class for each specialized type? If app.config is so suited as you say, I challenge you to take my simple demo and post sample code which uses app.config. Furthermore, demonstrate how more detailed structured storage would be stored in app.config, and how "easy" it would be.

3) app.config - See the name? App.config is for APPLICATION CONFIGURATION. Its not intended for user settings. App.config was designed for loading of assemblies and has a user section that you can read your own keys. You might specify DB connection, info or other if it is intended to change per installation, but not at program choice. It is not designed for user setting to be stored from the executable.

4) My method is about HOW to get the data in and out - not about WHERE to store it. This method could be used to embed items in the app.config - however that would still be a poor choice as the app.config is not designed for these types of settings.

For those interested in case phool_kevin doesnt bother to reply with real answers, these URLs can be followed to see that app.config is not meant to be written too, and if you choose too how much code is required:

Take a look at config.cs in the ZIP here:
http://www.thecodeproject.com/csharp/ReadWriteXmlIni.asp[^]

Thats for simple unstructured data....

Here is one that shows what you have to do just to even read custom type values as was suggested - mind you this is just to read:
http://www.thecodeproject.com/csharp/ConfigSectionHandler.asp[^]

Or ooh - how about this one?

http://weblogs.asp.net/jlerman/archive/2003/06/13/8649.aspx[^]

Quote from this site:
As the thread went on, it seemed evident that
Microsoft never intended for the .config files to be written to at run-time.
If you need to store per-user information, you will probably want to use
another mechinism such as the registry or by adding your on configuration
files to the user's profile. If you want more information, I suggest
searching groups.google.com.



Chad Z. Hower, a.k.a. Kudzu
"Programming is an art form that fights back"

My Technical Stuff:
http://www.hower.org/Kudzu/

My Software Blog:
http://blogs.atozed.com/kudzu/category/11.aspx
GeneralRe: An awkward solution Pin
Jon Rista25-Oct-04 12:12
Jon Rista25-Oct-04 12:12 
GeneralRe: An awkward solution Pin
Anonymous25-Oct-04 22:03
Anonymous25-Oct-04 22:03 
GeneralRe: An awkward solution Pin
Myrddin Emrys27-Oct-04 13:28
Myrddin Emrys27-Oct-04 13:28 
General.NET 2.0 Pin
Judah Gabriel Himango14-Oct-04 6:11
sponsorJudah Gabriel Himango14-Oct-04 6:11 
GeneralRe: .NET 2.0 Pin
Chad Z. Hower aka Kudzu14-Oct-04 6:20
Chad Z. Hower aka Kudzu14-Oct-04 6:20 
GeneralRe: .NET 2.0 Pin
Judah Gabriel Himango14-Oct-04 6:44
sponsorJudah Gabriel Himango14-Oct-04 6:44 
GeneralRe: .NET 2.0 Pin
Chad Z. Hower aka Kudzu16-Oct-04 7:34
Chad Z. Hower aka Kudzu16-Oct-04 7:34 
GeneralDifferent method Pin
totig14-Oct-04 3:30
totig14-Oct-04 3:30 
GeneralRe: Different method Pin
Chad Z. Hower aka Kudzu14-Oct-04 4:31
Chad Z. Hower aka Kudzu14-Oct-04 4:31 
GeneralNice Pin
sfawcett13-Oct-04 17:56
sfawcett13-Oct-04 17:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.