|
|
Use XML Files to Replace The Registry for GetSetting And SaveSetting VB Functions | | If your application has to save settings, you should not count on being able to write to the system Registry. Why not use an XML file to save your settings? More and more companies are locking down the registry on users computers. You are ultimately going to run into a problem if you use VBs SaveSetting function to save your applications settings. Obviously, none of us want to go back to the stone age of .INI files, uggh! This article shows you a code class that I wrote to solve the problem with XML.
This class provides overloaded methods of VBs GetSetting and SaveSetting functionality. I have written it so that no program changes have to be made, other than to instantiate an instance of the class and place the object instance name in front of all GetSetting and SaveSetting function calls. Actually, the class could have been written as a module (C# programmers, pretend I didn't use the word Module), and then it would not have to be instantiated. However, I wrote it as a class for several reasons. First, I program in both VB.NET and CSharp, so I am attempting to consider both languages as I write new code. C# does not support modules; rather it provides Shared Classes. You can do the same thing in VB.NET by making all methods and variables Shared. But, then I would have to place the name of the class as a prefix to all references to GetSetting or SaveSetting, just as if I were instantiating it as an object. Secondly, I have written the class so that an application could have multiple XML files (setting files) if desired. Additionally, the class is designed to imitate different user profiles having their own settings. In other words, if multiple users were to share one computer, with different logon names, this class will support either a shared setting file, or a setting file for each user.
As you examine the code for the class, you will see that the SaveSetting and GetSetting methods support the calls exactly as if the user were using the built-in VB.NET functions. That was on purpose so the user does not have to change the respective calls. You will note that the constructor accepts a Boolean name "AllUsers". If this Boolean is True, an XML file will be named just using the passed AppTitle string, pased to the respective Get and Set functions. However, if the Boolean is False, the class will append the UserName from the Environment as part of the XML filename, thus allowing multiple users to share a computer and your application, while maintaining their own settings. Finally, there is a Public property called "AlternatePath", which allows the user to supply the path where they want the settings saved. Again, not only do IT departments lock down the Registry, but they also protect the directory from which an application is executed. If this is the expected case, as it should be, then your application should prompt the installer for a temporary file path where it can write an XML file.
Initially, your application may not have any XML setting file(s), so the class will return the default values that your application passes when calling GetSetting.
I have only provided three Overloaded metods for each of the respective functions, because Integer, String, and Boolean will normally cover most application settings. If you need another type of setting, simply add a pair of overloads for the needed type.
Figure 1 shows the VB.NET code for the class. I know that C# programmers don't normally have access to GetSetting and SaveSetting (which from a VB programmers perspective, are great functions), so I have taken the time to convert the class to C#. I hope it might be used by a C# programmer.
The class is straight-forward, nothing fancy, so I won't bore you with further verbage on how it works. The following few lines show how to call the two methods.
Dim r As New CSettings(True)
CRegions.InsertRegionsInNewClass = _
r.GetSetting(AppTitle, Settings, "IRNC", "N")
r.SaveSetting(AppTitle, Settings, "IRNC", _
IIf(Me.optYesInsert.Checked, "Y", "N"))
|
Figure 1 - VB.NET Code for CSettings Class.
''' Purpose: Replacement Class for VB GetSetting and
''' ''' SaveSetting. Designed to replace the
''' saving of application Settings in the registry
''' with saving in an xml file in the installation directory.
''' Allows user to set an alternate path in case of install
''' directory lockdown. Allows user to have their own Settings
''' xml file or use one shared by all users on the same machine.
''' Allows user to have multiple "AppNames" creating multiple
''' xml files and multiple Settings (e.g., Settings, Registration, etc.)
''' Completely simulates VB GetSetting and SaveSetting by simply
''' instantiating this class and prefacing Get/SaveSetting calls with
''' the instance object name, e.g., r.GetSetting(....).
''' Author: Les Smith
''' Date Created: 01/24/2004 at 11:00:35
''' CopyRight: KnowDotNet
''' '''***************************************
'''
Option Strict On
Imports System
Public Class CSettings
#Region " Class Variables "
Private ds As DataSet
Private xmlFile As String = String.Empty
Dim _AllUsers As Boolean
Const XML As String = ".xml"
Private _AlternatePath As String = String.Empty
#End Region
#Region " Public SaveSetting Overloaded Methods "
Public Overloads Sub SaveSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal Key As String, _
ByVal Value As Boolean)
SaveSetting(AppTitle, Settings, Key, CStr(Value))
End Sub
Public Overloads Sub SaveSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal Key As String, _
ByVal Value As Integer)
SaveSetting(AppTitle, Settings, Key, CStr(Value))
End Sub
Public Overloads Sub SaveSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal Key As String, _
ByVal Value As String)
' this method sets or adds the value row for the passed key
Try
If xmlFile.Length = 0 Then SetupXMLFileName(AppTitle)
If ds Is Nothing Then
ds = New DataSet
Dim dt As DataTable = CreateDT(Settings, Key, Value)
ds.Tables.Add(dt)
Else
Dim dt As DataTable = ds.Tables(Settings)
If dt Is Nothing Then
' create new datatable named Settings
dt = CreateDT(Settings, Key, Value)
ds.Tables.Add(dt)
Else
Dim i As Integer
Dim b As Boolean
For i = 0 To dt.Rows.Count - 1
If CStr(dt.Rows(i).Item("key")) = Key Then
dt.Rows(i).Item("value") = Value
b = True
Exit For
End If
Next
If Not b Then
AddRow(dt, Key, Value)
End If
End If
End If
ds.WriteXml(xmlFile)
Catch ex As System.Exception
StructuredErrorHandler(ex)
End Try
End Sub
#End Region
#Region " Public Overloaded GetSetting Methods "
Public Overloads Function GetSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal key As String, _
ByVal keyvalue As Integer) _
As Integer
Dim o As Object = GetSetting(AppTitle, Settings, key, CStr(keyvalue))
If o Is Nothing Then
Return keyvalue
Else
Return CType(o, Integer)
End If
End Function
Public Overloads Function GetSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal key As String, _
ByVal keyvalue As Boolean) _
As Boolean
Dim o As Object = GetSetting(AppTitle, Settings, key, CStr(keyvalue))
If o Is Nothing Then
Return keyvalue
Else
Return CType(o, Boolean)
End If
End Function
Public Overloads Function GetSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal key As String, _
ByVal keyvalue As String) _
As Object
Dim i As Integer
Dim dr As DataRow
Dim dt As DataTable
Try
If xmlFile.Length = 0 Then SetupXMLFileName(AppTitle)
' this method returns the value specified by the key
If ds Is Nothing Then
dt = GetXml(Settings)
If dt Is Nothing Then Return keyvalue
Else
dt = ds.Tables(Settings)
End If
For i = 0 To dt.Rows.Count - 1
dr = dt.Rows(i)
If CStr(dr("Key")) = key Then
Return dr("Value")
End If
Next
Return keyvalue
Catch ex As System.Exception
StructuredErrorHandler(ex)
End Try
End Function
#End Region
#Region " Private Methods "
Private Function CreateDT(ByVal Settings As String, ByVal key As String, _
ByVal value As Object) As DataTable
Dim dt As DataTable
dt = New DataTable(Settings)
dt.Columns.Add("Key", Type.GetType("System.String"))
dt.Columns.Add("Value", Type.GetType("System.String"))
AddRow(dt, key, value)
Return dt
End Function
Private Sub AddRow(ByRef dt As DataTable, ByVal key As String, _
ByVal value As Object)
Dim newRow As DataRow = dt.NewRow
newRow(0) = key
newRow(1) = value
dt.Rows.Add(newRow)
End Sub
Private Function GetXml(ByVal tablename As String) As DataTable
If Not IO.File.Exists(xmlFile) Then
Return Nothing
End If
ds = New DataSet
ds.ReadXml(xmlFile)
Dim dt As DataTable = ds.Tables(tablename)
Return dt
End Function
Private Sub SetupXMLFileName(ByVal fn As String)
' Returns filename for xmlfile, generated by using
' AppTitle suppliied to the two public methods and then
' boolean supplied to the constructor.
' install directory may be locked so check to see if
' caller supplied an alternate directory.
Dim s As String
If _AlternatePath.Length = 0 Then
s = IO.Path.GetDirectoryName( _
Reflection.Assembly.GetExecutingAssembly.Location())
Else
s = IO.Path.GetDirectoryName(_AlternatePath)
End If
If _AllUsers Then
xmlFile = s & "\" & fn & XML
Else
xmlFile = s & "\" & fn & "_" & Environ("UserName") & XML
End If
End Sub
#End Region
#Region " Constructor "
Public Sub New(ByVal AllUsers As Boolean)
Me._AllUsers = AllUsers
End Sub
#End Region
#Region " Property Methods "
Public Property AlternatePath() As String
Get
Return _AlternatePath
End Get
Set(ByVal Value As String)
_AlternatePath = Value
End Set
End Property
#End Region
End Class
|
Top of Page
Figure 2 - C# Code for CSettings Class.
using System;
using System.Reflection;
using System.Data;
namespace CSharp2003WindowsApplication1
{
/// <summary>
/// Summary description for CSettings.
///
public class CSettings
{
#region " Class Variables "
private DataSet ds;
private string xmlFile = String.Empty;
private bool m_AllUsers;
const string XML = ".xml";
private string m_AlternatePath = String.Empty;
#endregion
#region " SaveSetting Methods "
public void SaveSetting(string AppTitle,
string Settings, string Key, bool Value)
{
SaveSetting(AppTitle, Settings, Key, Value.ToString());
}
public void SaveSetting(string AppTitle,
string Settings, string Key, int Value)
{
SaveSetting(AppTitle, Settings, Key, Value.ToString());
}
public void SaveSetting(string AppTitle,
string Settings, string Key, string Value)
{
if (xmlFile.Length==0)
SetupXMLFileName(AppTitle);
if (ds == null)
{
ds = new DataSet();
DataTable dt = CreateDT(Settings,Key,Value);
ds.Tables.Add(dt);
}
else
{
DataTable dt = ds.Tables[Settings];
if (dt == null)
{
// create new datatable
dt = CreateDT(Settings,Key,Value);
ds.Tables.Add(dt);
}
else
{
bool b=false;
for (int i = 0; i < (int) dt.Rows.Count;i++)
{
if((string)dt.Rows[i].ItemArray[0] == Key)
{
dt.Rows[i].ItemArray[1] = Value;
b = true;
break;
}
}
if (b != true)
AddRow(ref dt, Key, Value);
}
}
ds.WriteXml(xmlFile);
}
#endregion
#region " GetSetting Methods "
public int GetSetting(string AppTitle, string Settings,
string Key, int KeyValue)
{
string o = GetSetting(AppTitle,Settings,Key,KeyValue.ToString().ToLower());
if (o == null)
return KeyValue;
else
return int.Parse(o);
}
public bool GetSetting(string AppTitle, string Settings,
string Key, bool KeyValue)
{
string o = GetSetting(AppTitle,Settings,Key,KeyValue.ToString().ToLower());
if (o == null)
return KeyValue;
else
return bool.Parse(o);
}
public string GetSetting(string AppTitle, string Settings,
string Key, string KeyValue)
{
DataRow dr;
DataTable dt;
if (xmlFile.Length == 0)
SetupXMLFileName(AppTitle);
if (ds == null)
{
dt = GetXml(Settings);
if (dt == null)
return KeyValue;
}
else
dt = ds.Tables[Settings];
for (int i = 0; i < dt.Rows.Count; i++)<BR>
{
dr = dt.Rows[i];
if ((string) dr["Key"] == Key)
return (string) dr["Value"];
}
return KeyValue;
}
#endregion
#region " Private Methods "
private DataTable CreateDT(string Settings,string Key,string Value)
{
DataTable dt;
dt = new DataTable(Settings);
dt.Columns.Add("Key",Type.GetType("System.String"));
dt.Columns.Add("Value",Type.GetType("System.String"));
AddRow(ref dt,Key,Value);
return dt;
}
private void AddRow(ref DataTable dt,
string Key, object Value)
{
DataRow newRow = dt.NewRow();
newRow[0] = Key;
newRow[1] = Value;
dt.Rows.Add(newRow);
}
private DataTable GetXml(string tablename)
{
if (!System.IO.File.Exists(xmlFile))
return null;
ds = new DataSet();
ds.ReadXml(xmlFile);
DataTable dt = ds.Tables[tablename];
return dt;
}
/* Returns filename for xmlfile, generated by using
AppTitle suppliied to the two public methods and then
boolean supplied to the constructor.
install directory may be locked so check to see if
caller supplied an alternate directory.
*/
private void SetupXMLFileName(string fn)
{
string s;
if (m_AlternatePath.Length == 0)
s = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.
GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
else
s = System.IO.Path.GetDirectoryName(m_AlternatePath);
// compact framework not supported
if(m_AllUsers==true)
xmlFile = s + "\\" + fn + XML;
else
xmlFile = s + "\\" + fn + "_" + Environment.UserName + XML;
}
#endregion
#region " Constructor "
public CSettings(bool AllUsers)
{
m_AllUsers = AllUsers;
}
#endregion
#region " Public Properties "
public bool AllUsers
{
get {
return (bool) m_AllUsers;
}
set {
bool m_AllUsers= value;
}
}
public string AlternatePath
{
get
{
return m_AlternatePath;
}
set
{
m_AlternatePath = value;
}
}
#endregion
}
}
|
Top of Page
|
|