Click here to Skip to main content
15,867,756 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 348.5K   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

 
QuestionAnybody modify this to do it in a loop? Pin
Kraig_mn20-Sep-13 4:51
Kraig_mn20-Sep-13 4:51 
AnswerRe: Anybody modify this to do it in a loop? Pin
Chad Z. Hower aka Kudzu20-Sep-13 4:53
Chad Z. Hower aka Kudzu20-Sep-13 4:53 
GeneralRe: Anybody modify this to do it in a loop? Pin
Kraig_mn20-Sep-13 4:58
Kraig_mn20-Sep-13 4:58 
GeneralRe: Anybody modify this to do it in a loop? Pin
Chad Z. Hower aka Kudzu20-Sep-13 11:11
Chad Z. Hower aka Kudzu20-Sep-13 11:11 
GeneralRe: Anybody modify this to do it in a loop? Pin
Kraig_mn23-Sep-13 5:07
Kraig_mn23-Sep-13 5:07 
GeneralRe: Anybody modify this to do it in a loop? Pin
Kraig_mn23-Sep-13 5:54
Kraig_mn23-Sep-13 5:54 
GeneralDataSet.ReadXml has arror Pin
Makso13-Aug-09 22:18
Makso13-Aug-09 22:18 
GeneralRe: DataSet.ReadXml has arror Pin
Chad Z. Hower aka Kudzu14-Aug-09 3:46
Chad Z. Hower aka Kudzu14-Aug-09 3:46 
GeneralRe: DataSet.ReadXml has arror Pin
Makso17-Aug-09 23:56
Makso17-Aug-09 23:56 
GeneralRe: DataSet.ReadXml has arror Pin
Chad Z. Hower aka Kudzu18-Aug-09 15:37
Chad Z. Hower aka Kudzu18-Aug-09 15:37 
Generalgood article Pin
Donsw8-May-09 16:24
Donsw8-May-09 16:24 
GeneralTrue but.... Pin
AhsanS9-Nov-08 17:33
AhsanS9-Nov-08 17:33 
GeneralRe: True but.... Pin
Chad Z. Hower aka Kudzu18-Nov-08 15:15
Chad Z. Hower aka Kudzu18-Nov-08 15:15 
QuestionHow to secure these settings? Pin
vinay_kawade14-Jul-08 13:12
vinay_kawade14-Jul-08 13:12 
AnswerRe: How to secure these settings? Pin
Chad Z. Hower aka Kudzu14-Jul-08 13:31
Chad Z. Hower aka Kudzu14-Jul-08 13:31 
QuestionAdd a field later? Pin
StephenKearney15-Sep-07 10:11
StephenKearney15-Sep-07 10:11 
AnswerRe: Add a field later? Pin
Chad Z. Hower aka Kudzu8-Oct-07 7:36
Chad Z. Hower aka Kudzu8-Oct-07 7:36 
Generali know you from somewhere... Pin
ferdna8-Sep-07 9:56
ferdna8-Sep-07 9:56 
GeneralRe: i know you from somewhere... Pin
Chad Z. Hower aka Kudzu2-Feb-08 0:16
Chad Z. Hower aka Kudzu2-Feb-08 0:16 
GeneralMultiple Dtata tables Pin
sid_boss16-Mar-07 2:10
sid_boss16-Mar-07 2:10 
GeneralRe: Multiple Dtata tables Pin
Chad Z. Hower aka Kudzu2-Feb-08 0:17
Chad Z. Hower aka Kudzu2-Feb-08 0:17 
GeneralDarn It Pin
SteveWaNet24-Nov-06 17:42
SteveWaNet24-Nov-06 17:42 
GeneralRe: Darn It Pin
SteveWaNet25-Nov-06 7:27
SteveWaNet25-Nov-06 7:27 
GeneralRe: Darn It (No Element is VS 2008 Team Suite) [modified] Pin
Michael90003-Dec-09 16:10
Michael90003-Dec-09 16:10 
GeneralButton backcolor Pin
The Mighty Atom1-Sep-06 7:48
The Mighty Atom1-Sep-06 7:48 
Great article!

I was wondering, how can you save/load backcolors of controls? I have a couple of buttons in my app to show a color to the user. This is done with a colordialog control.

I've added this to the butnSave_Click event:

xRow.Color = view32Dialog.Color.R & ChrW(32) & view32Dialog.Color.G & ChrW(32) & view32Dialog.Color.B

When you click a button, a colordialog appears where the user selects a color. After that, a flat button you cannot click, shows that color. When i click the Save button, the rgb values of that color are written as:

<color>xxx xxx xxx
(xxx xxx xxx = R G B)

in the settings file. So far so good.

But i can't seem to load the color so that it is applied on the button. I tried this:

If Not xRow.IsColorRNull() Then
view32Dialog.Color = xRow.Color
End If

This doesn't work. The words xRow.Color are blue underlined, and i get the message "Error: Value of type 'String' cannot be converted to 'System.Drawing.Color". So im kinda stuck here.

Can you help me?

I also succesfully added a combobox control and this works fine, since this is pretty much like a textbox. Smile | :)

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.