A long time ago, in May of 2003, I have written an article on applications settings. Since then many things changed in this area, I think that it would be great to review this topic. This time, I won’t spend any time talking of other ways of storing applications and/or using settings other then what is available in the ConfigurationSettings class. This class was greatly enhanced in .Net 2.0.
What’s new in AppSettings?
In the versions 1.x of the .Net framework, the application settings files (aka app.config) was an easy way to deliver the settings required by an application that you don’t want to hardcode into your application. This file was read-only.
The newest version now allows differentiating applications settings from users’ settings.
Applications settings should be read-only by the application and provided by programmers. A good example of an application setting is the connection string. Users should never be allowed to modify that value directly. That kind of settings was almost OK in the previous version (no easy encryption).
On the other hand, it was not possible to save user settings and it is now possible. Some example of user settings you might find useful to save includes form’s size and location settings.
Another great improvement to the configuration settings is that they are now strongly type. This will surely help reduce errors and simplify your code.
Creating the configuration files
There are many ways of creating the configuration file. I will show you one here. After you have opened a new Windows application, open the properties of your project. Then on the left border, select the Settings tab (you will see something like shown in figure 1 but with no values in it).
Figure 1: The Settings tab
In this screen, you see 4 fields that you must fill. The first field is really simple: what is the name you want to give to your value. Notice that this name must be unique (otherwise you will get an error message). The second column requires you to provide the type of the value. The value column will then adapt to this data type. The third column requires you to specify if this value is an application setting or a user setting (settings that the user will be able to save). The last column is the value itself. The editor provided to edit the last column depends on the Type column. For example, for my (Connection string) type, I got ellipsis into the value column that allowed me to create a connection string using the Connection Properties dialog.
Where are those values stored?
After you have added some values into the Settings tab, a new file is added to your project (if one does not already exist). Its name is app.config (as shown in figure 2).
Figure 2: app.config is added to the project
When you will build your project, this file will be moved to your bin folder and renamed to the same name as your executable file but with a .config file extension. In my example, my Demo project is compiled to Demo.exe so the configuration file is renamed to Demo.exe.config.
This configuration file is simply a XML file. You might be tempted in editing this file directly into the bin folder but never – never - never do that! Every time you will rebuild your project, this file will be recreated. And don’t even try to put as a read-only file or you will receive a compile error (Unable to copy file “app,config” to bin\…).
Reading a value from the configuration file
Now that we have a value in our configuration file, you might ask how easy it is to read a value from your application. Is a single line of code would be easy enough for you? In the following line, you are setting the Text property of a Label control to the value of the ConnectionString setting (created in the previous step – see figure 1).
lblConnectionString.Text = My.Settings.ConnectionString
Binding UI objects to application settings
You can also bind some of these settings directly to objects of your application. You can either create your settings upfront or let the IDE create it for you.
Let’s say we want to store the Text property of the form into the configuration file and bind it to the Form object directly. For this purpose, you need to open the (ApplicationSettings) property, click the Text property, and click the down arrow (as you can see in figure 3).
Figure 3: Binding settings to objects
If your value already exists, you just need to select it from the list that is shown. In my case, the value does not exist and we want to create one. All you have to do is to click the (New…) link at the bottom of this dialog to display another dialog that will let you enter values for your new settings (as shown in figure 4).
Figure 4: Creating new application settings
You find in this dialog the same information we add to give using the first method (see figure 1) except the Type column that is not there (but the type follows the type of the property we are currently setting – and in our example, the Text property is a String).
After you clicked the OK button, the form in the designer has a new caption. If you return to the project properties, you will also see that your new configuration setting is there. It is just another method of adding values to the application settings.
After you bound a property to a configuration setting, you will see a small icon in the Properties dialog for this property as shown in figure 5. If you modify the value of one of those properties, modifications will be saved into the app.config as well so you don’t always have to return to the project properties to modify values.
Figure 5: A bound property
So far, I showed how to use settings for the application. Those values won’t be updatable by the user.
If you remember, I have announced that we can also handle settings that belong to the users.
To demo this feature, I will let the user change the BackColor property of the form (how useful it is?).
We first need to bind the BackColor property of the form to a new value much like we just did for the form’s caption. So you need to go back the (ApplicationSettings) property (as shown in figure 3) to discover that … the BackColor property is not listed there! Don’t panic; click the ellipsis button on the right of the (PropertyBinding) property. This will open another dialog showing you all properties that can be bound. Find the BackColor property in this list and click the down arrow and the (New…) link as shown in figure 6. You are probably expecting to see our 2 others settings we have already added but there not there. Can you guess why they are not listed? The answer is really simple. This list only shows values having a compatible data type to the current property. The 2 current settings are of type text, we now want to enter a color!
Figure 6: Binding the BackColor property.
So click the (New…) link and enter some values as shown in figure 7. Be very cautious in keeping the scope property to User.
Figure 7: Typical values for the BackColor property
Now because it is a user setting, we need to let the user change this setting. For this, we will add a button to our form and use the ColorDialog component to let the user select another color. When the user has selected a new color, you need to affect this selection to the value created in the previous step (FormBackColor is the name of the value created in figure 7) and because your form BackColor’s property is bound to this value, it will automatically be updated as well:
Dim objColorDlg As New ColorDialog
If objColorDlg.ShowDialog = Windows.Forms.DialogResult.OK Then
My.Settings.FormBackColor = objColorDlg.Color
Where user settings’ are persisted?
We have added a user value (named FormBackColor) that is visible in the Settings tab of the project’s properties (see figure 1). This value was added to the app.config file, moved and renamed as Demo.exe.config file in the bin folder. You ran the application and discovered that the new color was automatically persisted.
Does this mean that if you ever need to update your application settings in the configuration file that the users will loose all there own settings? If 2 users are using the same computer, will they share the same settings? Are you curious about knowing where the user settings are persisted?
In fact, everything is OK. Users’ settings are persisted deep in folders hierarchy. You can normally find a file named user.config somewhere in:
C:\Documents and Settings\UserName\Local Settings\Application Data
But there is one problem I found! Search for the user.config file created for you and you will find that part of the path includes the assembly version. If you ever changed the version number, a new folder will be created and all the settings will be lost.
The only workaround I found to this problem is to create another user scoped value in your configuration file, name it CallUpgrade, give it a Boolean type and set its value to True. Finally, when the application starts, check if you need retrieve previous values like this:
If My.Settings.CallUpgrade Then
My.Settings.CallUpgrade = False
Are settings always saved on shutdown?
You have seen that users’ settings were automatically persisted but this is not always the case.
We had this behavior because the “Save My.Settings on ShutDown” property of the project (see figure 8) was selected. This setting is available from the application tab of your project settings.
Figure 8: The auto save property
If you don’t want to automatically save your settings, you can simply use the Save method like this:
Adding a connection string that is human readable into the configuration file is not very safe. There are many workarounds to that.
The first one is that you can use the same method as ASP.Net programmers are using to encrypt their web.config file. This is explained at http://msdn2.microsoft.com/en-us/library/53tyfkaw.aspx.
You could also use another very simple approach that I will show you there. This method will store the connection string as an encrypted string into the configuration file.
I will borrow the cTripleDES class of Tony Selke that you can find on CodeProject (http://www.codeproject.com/vb/net/VB_NET_TripleDES.asp). The method I use here is really simple but requires some manual operations from you.
I have added a button to my form that encrypt the connection string we have created in one of the first steps and put the result into a read-only textbox (so that we can easily copy-and-paste the value from it):
txtEncryptedCS.Text = des.Encrypt(lblConnectionString.Text)
Finally, you need to decrypt this value when the application starts (or whenever it is required) using a simple line like this:
lblEncryptedCS.Text = des.Decrypt(My.Settings.EncryptedCS)
Many great new features have been added to configuration management and make it even easier to use from any application.
I hope you appreciated the topic and see you next month.