All Windows applications need to persist some data. Here I can think of three different kinds of data. The first kind of data is normally kept into a database. An application has been created to handle that data (customers, invoices, books, authors, …). I won't talk about that kind of data in this article. The second kind of data is parameters for applications. Some of these parameters are better stored in a database (mail server, tax percentage, …) but others (like the connection string) are better kept elsewhere. The third kind of data is users settings. An application should persist some of the settings of users like forms position and size, preferred language, and so on. These could be stored into the database but I prefer to save them locally. There are advantages to persisting user's data to a central database (like the user's mobility) but in the client-server world, users do not switch from PC to PC quite often! The main disadvantage is the bad performance over slow network.
So my topic this month, as you may have already guessed, is the persistence of settings locally. I will give you some thoughts and code on four different ways of persisting that kind of data. The first method is the legacy .INI files. The second method is the Windows Registry database. The third method is XML files used with the Configuration namespace. The last, but not least, is XML used with its own library. All the code won't be listed through the article (for clarity reason). You will find a link at the bottom to download a complete project with demos of each method.
Method 1: The .INI files
This is probably the most used method as of today. These files are common since the beginning of Windows (do you remember system.ini and win.ini?). These files, very easy to edit, have a simple structure like this:
[Database] Environment=Development
Private Declare Unicode _ Function GetPrivateProfileString _ Lib "kernel32" _ Alias "GetPrivateProfileStringW" _ (ByVal lpApplicationName As String, _ ByVal lpKeyName As String, _ ByVal lpDefault As String, _ ByVal lpReturnedString As String, _ ByVal nSize As Int32, _ ByVal lpFileName As String) As Int32
With the INIAccess class somewhere in your project, you can easily use it like in the following example that opens c:\test.ini and retrieves the value of the Environment key from the Database section. If this key does not exist, the message box will display a default value ("--- Not Found ---").
Dim x As New INIAccess() MessageBox.Show(x.INIRead("c:\test.ini", _ "Database", _ "Environment", _ "--- Not Found ---"))
Method 2: The Registry
The main disadvantage of the registry is that it may not be as easy to distribute and edit as other methods. We also all have eared of corruption and problems caused by some hazardous manipulation of the registry. Another fact to consider is that values are user-based (because we are normally restricted to save values into HKEY_Current_User). If we logon as another user, we cannot have access to the values previously persisted by another user.
For example, this is the code required for you to write values into the registry (you need to Imports Microsoft.Win32 at the top of this module).
Dim k As RegistryKey k = Registry.CurrentUser.OpenSubKey("Software\\Emoreau", True) If k Is Nothing Then k = Registry.CurrentUser.CreateSubKey("Software\\Emoreau") End If k.SetValue("Test1", "v1") k.Close()
These lines will be saved the value into the HKEY_CURRENT_USER\Software\Emoreau name (as you can see in the screenshot). If the branch does not already exist, it will be created (because of the CreateSubKey method) . Retrieving values is as easy (download the code for the demo).
Figure 1: The values saved into the Registry.
Method 3: The Windows Forms configuration files
The .Net Framework gives us the System.Configuration namespace in which we can find the ConfigurationSettings class. This class exposes the AppSettings property that allows us to read the content of a particular section of a particular XML file. What is so particular with this file? It needs to respect a strict formatting of filename and section name. Here is an example of this file:
<?xml version="1.0" encoding="utf-8"?> <configuration> <appSettings> <add key="env" value="test" /> <add key="cs" value="initial catalog=Pubs" /> </appSettings> </configuration>
The best part of it is the little code required to read this file. After you imported System.Configuration, you only need a simple line like this one:
MessageBox.Show(ConfigurationSettings.AppSettings("env"))
Oh sorry, have I told you that this namespace only allows you to read the file? But for application settings that are normally not modified by users, it is just perfect!
Method 4: XML files
The last method I want to talk about is the use of real XML files. If you download the demo project, you will find a complete class in it (named AppSettingsManager.vb). I cannot take credits for this class. I need to give the credits to A. Russell Jones (see How to Make Your .NET Windows Forms Configuration Files Dynamic in the references). The beauty of this class is that it includes methods such as GetValue, AddValue, KeyExists, Remove, Save to handle just about any operations on the file.
Here is a sample of the use of this class:
Dim cm = AppSettingsManager.GetManager() ' add single values cm.AddValue("v5", "Value 5") cm.AddValue("v6", "Value 6") ' remove single values If cm.KeyExists("v4") Then cm.Remove("v4") End If
Conclusion
As you have seen in this article, persisting and using applications (or users) settings is really easy. I hope that you will consider using one of the methods described above to store your applications settings instead of hard coding them (because there are still people that hardcode the connection string!). Also, be sweet to your users and persist there settings like forms position and size. Why not create your own form that includes this feature and always inherits this base form so that you will write this code once for all? I am sure that you like when you open Word, Excel, Visual Studio or any other applications and find it at the same place you left it!
Here are some references related to this topic.
I hope you appreciated the topic and see you next month.