Saving and Retrieving Application Settings

reboot
12-29-2003, 08:36 PM
First of all a config file synopsis.

With the advent of .Net we seem to have come full circle in regard to application settings. Back in the pre-95 days Microsoft invented ini files, and told us they were good. And so they were. Then along came 95 and NT, and Microsoft said no, the registry is the way to go, forget ini files. And so we did. Now in .Net we're told to use config files, which is basically the same concept as an ini file, albeit being XML, it’s an ini file on steroids.

You’ll notice in your apps project directory a file named app.config and in your project/bin directory a file named projectname.exe.config. .Net provides a System.Configuration.AppSettingsReader Class (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemconfigurationappsettingsreaderclasstopic.asp) to “read” settings from app.config. While there is a GetValue method for reading you’ll find no matching SetValue method for writing. Finding this very unhandy, I decided to write my own that included a Write method.

Originally, I had mine writing to the projectname.exe.config file, not knowing any better, then noticed that app.config overwrites this file every time you run in the IDE. Even though it works fine in a compiled executable running outside the IDE, after doing some research, I discovered that I shouldn’t have been writing to that file in the first place. Microsoft recommends that you do not have files in the Program Files directory writeable to users as this is a security risk. They further recommend that you store your configuration files in another location, preferably in the Application Data folder in the Documents and Settings folder.

And so the following code was born. Since I’ve always rather liked the ability to use the Current_User/Local_Machine sections in the registry to have, respectively, individual settings and shared settings, I included this functionality in the class. I also used the familiar GetSetting/SaveSetting terminology from VB6. There are probably several areas for improvement, more error handling, possibly the ability to save/retrieve data types other than just string, etc, but I’ll leave that to you for now.
Imports System
'a class for reading and writing XML style application settings
'sample usage:
' Create the object -
' Dim a As New AppSettings(AppSettings.Config.PrivateFile)
' Retrieve a setting -
' Dim myString As String = a.GetSetting("SettingName")
' Save a setting -
' a.SaveSetting("SettingName", value)
'
Public Class AppSettings
Private _configFileName As String 'local var to hold the config file name
Private _configFileType As Config 'local var to hold the config file type (private or shared)

'config file options
Public Enum Config
SharedFile 'all users use the same config file
PrivateFile 'each user has their own config file
End Enum

'constructor
Public Sub New(ByVal ConfigFileType As Config)
_configFileType = ConfigFileType 'remember this setting

InitializeConfigFile() 'setup the filename and location
End Sub

'initialize the apps config file, create it if it doesn't exist
Private Sub InitializeConfigFile()
Dim sb As New Text.StringBuilder

'build the path\filename depending on the location of the config file
Select Case _configFileType
Case Config.PrivateFile 'each user has their own personal settings
'use "\documents and settings\username\application data" for the config file directory
sb.Append(Environment.GetFolderPath(Environment.SpecialFolder.Applicat ionData))
Case Config.SharedFile 'all users share the same settings
'use "\documents and settings\All Users\application data" for the config file directory
sb.Append(Environment.GetFolderPath(Environment.SpecialFolder.CommonAp plicationData))
End Select

'add the product name
sb.Append("\")
sb.Append(Application.ProductName)

'create the directory if it isn't there
If Not IO.Directory.Exists(sb.ToString) Then
IO.Directory.CreateDirectory(sb.ToString)
End If

'finish building the file name
sb.Append("\")
sb.Append(Application.ProductName)
sb.Append(".config")

_configFileName = sb.ToString 'completed config filename

'if the file doesn't exist, create a blank xml
If Not IO.File.Exists(_configFileName) Then
Dim fn As New IO.StreamWriter(IO.File.Open(_configFileName, IO.FileMode.Create))
fn.WriteLine("<?xml version=""1.0"" encoding=""utf-8""?>")
fn.WriteLine("<configuration>")
fn.WriteLine(" <appSettings>")
fn.WriteLine(" <!-- User application and configured property settings go here.-->")
fn.WriteLine(" <!-- Example: <add key=""settingName"" value=""settingValue""/> -->")
fn.WriteLine(" </appSettings>")
fn.WriteLine("</configuration>")
fn.Close() 'all done
End If
End Sub

'get an application setting by key value
Public Function GetSetting(ByVal key As String) As String
'xml document object
Dim xd As New Xml.XmlDocument

'load the xml file
xd.Load(_configFileName)

'query for a value
Dim Node As Xml.XmlNode = xd.DocumentElement.SelectSingleNode( _
"/configuration/appSettings/add[@key=""" & key & """]")

'return the value or nothing if it doesn't exist
If Not Node Is Nothing Then
Return Node.Attributes.GetNamedItem("value").Value
Else
Return Nothing
End If
End Function

'save an application setting, takes a key and a value
Public Sub SaveSetting(ByVal key As String, ByVal value As String)
'xml document object
Dim xd As New Xml.XmlDocument

'load the xml file
xd.Load(_configFileName)

'get the value
Dim Node As Xml.XmlElement = CType(xd.DocumentElement.SelectSingleNode( _
"/configuration/appSettings/add[@key=""" & _
key & """]"), Xml.XmlElement)
If Not Node Is Nothing Then
'key found, set the value
Node.Attributes.GetNamedItem("value").Value = value
Else
'key not found, create it
Node = xd.CreateElement("add")
Node.SetAttribute("key", key)
Node.SetAttribute("value", value)

'look for the appsettings node
Dim Root As Xml.XmlNode = xd.DocumentElement.SelectSingleNode("/configuration/appSettings")

'add the new child node (this key)
If Not Root Is Nothing Then
Root.AppendChild(Node)
Else
Try
'appsettings node didn't exist, add it before adding the new child
Root = xd.DocumentElement.SelectSingleNode("/configuration")
Root.AppendChild(xd.CreateElement("appSettings"))
Root = xd.DocumentElement.SelectSingleNode("/configuration/appSettings")
Root.AppendChild(Node)
Catch ex As Exception
'failed adding node, throw an error
Throw New Exception("Could not set value", ex)
End Try
End If
End If

'finally, save the new version of the config file
xd.Save(_configFileName)
End Sub
End Class

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum