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.

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.

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.

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

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.

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:

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:

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#
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
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.

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.
="1.0" ="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.
| You must Sign In to use this message board. |
|
|
 |
 | DataSet.ReadXml has arror Makso | 23:18 13 Aug '09 |
|
 |
Good day!
Can You help me please?
I have this problem:
When I use DataSet.ReadXml method for read xml file
SHYMKENT_SF Тип
then message is appears - An anhandled exception of type 'System.Xml.XmlException' occured in system.xml.dll (Additional information: System error)
I think its error appears because I use russion text in file - Тип. How to solve this problem?
TIA, Max.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I cant see your error, so I cant help much. Russian text should be no problem. If you want to send me a standalone ready to run project I can take a look at it.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Forgive me for a question. I have understood in what a problem.
If to create an xml-file through a windows notepad, and to add in it the Russian text at its opening the Internet Explorer will be an error.
If the xml-file has been created during save DataSet, there is the same.
I have created an xml-file in Visual Studio and at me all has earned.
HAGO, Makso.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Try running the program and having it create the XML file. Also check the encoding options, I don't remember what I used or if I specified a hard coded one.
If you use Notepad or other, you will need to make sure it saves as Unicode and also the VS reads it in as Unicode rather than ANSI.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
 | good article Donsw | 17:24 8 May '09 |
|
|
 |
 | True but.... AhsanS | 18:33 9 Nov '08 |
|
 |
Hi Chad,
Your solution is fine and will work well. You have explained it well enough too, but datasets are not meant for this purpose. Simply using XPath and providing expressions to get values is the right way of doing it for me.
Ahsan Ullah Senior Software Engineer MCTS 2.0
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Of course Datasets were not designed for this. They just work very well, and epescially when I wrote this .NET 1.1 was the only version out. Since then there are many more options. There is nothing wrong with raw XML, but its more work for most especially those no familiar with the deeper details of XML.
But even in the world of .NET 3.5 I find myself often using datasets because they are very easy to use.
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
 | How to secure these settings? vinay_kawade | 14:12 14 Jul '08 |
|
 |
Hi Chad,
Some one can easily change the content of the XML file.
In the above example, one can simply go to the config file path and change the user PIN?
how do you prohibit that.
Where do I keep the data that needs to be secured?
VInK
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
That is actually a feature most people want. The ability for users to edit.
If you want to hide something, you need to encrypt it. The level of encryption depends on the data. You can also encxrypt just individual keys, instead of the whole file.
There are encryption functions built into .NET, or for passwords and things you can use easier more standard practices of storing hashes. Which hash/encryption again depends on your required security level.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
 | Add a field later? StephenKearney | 11:11 15 Sep '07 |
|
 |
Great article. Thanks to it I'm successfully using XML files for application settings and data. However I realize that I may run into a problem in the future. Because my application is constantly being improved I add new features to it now and then. If I need to store any new data I'll have to revise my dataset by adding fields. If I then try to load an old XML file (from before the fields were added) it will throw an exception due to the fields mismatch.
Is there any elegant way to get around this limitation? I could write some functions to identify the version of the dataset in the XML file and then convert old to new versions but that seems a bit clunky. There must be a better way (at least I'm hoping there is).
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
This should only happen if you change data types or add new fields that are required.
If you need to do that, you can version your files by embedding version information.
However since .NET 2.0 there are built in settings classes that replace much (not all, some cases my method is better) of this funciontality. You should check them out too.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
 | i know you from somewhere... ferdna | 10:56 8 Sep '07 |
|
 |
chad... i think i remember you!!!!!!! wheren't you a hardcore Borland Delphi developer...??? nice seen you in the .net world...
It Is Not That I'm Different! ... I'm Only Making The Difference!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
 | Multiple Dtata tables sid_boss | 3:10 16 Mar '07 |
|
 |
This is a great article...I was just wondering what would be the best way to handle multiple data tables writing to the same file...coz it seems that the current method suggested will create a new settings file everytime and hence remove the sections corresponding to other tables..do i need to fill the DS everytime i plan to update a table?
please excuse if the query is silly, but am new to all this...
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
|
 |
 | Darn It SteveWaNet | 18:42 24 Nov '06 |
|
 |
This looks like such the perfect solution for my winforms app I'm writing. But then I open up my Solution in C# Express Edition, add a DataSet, and... it's the end of my game:
Express Edition has only a mere fraction of the "tools" in the toolbox for Dataset.
No Element.
Only TableAdapter, Query, Datatable, and Relation.
I think I'll just read up on how to serialize on object to xml and do it the manual way.
Thanks for the code, though. I'll probably ending using in the futre. Steve
"Just trust yourself, then you will know how to live." - Goethe
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
For those with Express Edition, I found the following
http://www.builderau.com.au/program/dotnet/soa/Use_XML_to_store_configuration_settings/0,339028399,339211304,00.htm
But, anyhow, thanks again Chad.
"Just trust yourself, then you will know how to live." - Goethe
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Well I have the same problem - no Element in the ToolBox - and that is with VS2008 Team Suite!
Am I missing a reference or something else?
Edit: No missing reference. It's the same in the demo. Do I need to add something to the ToolBox to add a Element to the DataSet?
You got my 5, though it's an rather old article, it has some good points
modified on Thursday, December 3, 2009 10:20 PM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
 | Button backcolor The Mighty Atom | 8:48 1 Sep '06 |
|
 |
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:
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.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
When you are saving Color you are converting it to a string. If you want to store it that way, when you read it back you need to convert it to the type that color is. I'm not at my dev PC now, but IIRC Color might be a descendant of int.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thanks.
But im affraid i need some more help with that. See, im just a student, and pretty new to .NET
You say that i need to convert it to the type that color is. I tried Integer and string, and none of them work. It saved the color rgb's as string, but i cannot convert the string back to color. Or something like that.
Could you help me out? Thanks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Im not able to look right now as Im preparing to fly out. Check the type of color and see if it descends from Int. If not, look at parsing routines to convert string back to it.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Im don't really know what you meen by that, but ill try. I tried many things like:
- With and without the Trim thingy. - With and without the ToString thingy. - With and without the view32dialog. - With and without the Parse thingy. - Tried System.Int32 and System.String in the Settings.xsd file. - xRow.Color = view32Dialog.Color.R & ChrW(32) & view32Dialog.Color.G & ChrW(32) & view32Dialog.Color.B - xRow.Color = view32Dialog.Color.ARGB - And many more things and variations, i just can't get it to work.
I keep on getting errors. My geuss it that it doesn't know what to do with the RGB string, since it is not a color value yet.
This is a pain in the butt, because my app will be completed when i have this working.
A color value from a ColorDialog, is that a String, Integer or even an Object type?
Geuss ill have to wait untill you're back, you're my only hope!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
My app is still not finished because im still stuck with this. I really need help with this, i tried everything and could'nt get it to work.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
save r, g and b to settings
Button btn = new Button(); int r = btn.BackColor.R; int g = btn.BackColor.G; int b = btn.BackColor.B;
load r, g and b from settings
Color c = Color.FromArgb(int red, int green, int blue); btn.BackColor = c;
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|