One of the problems Microsoft solved with .NET was the convoluted installation procedure required for most applications. .NET applications don’t need any complicated installation procedure (assuming the .NET framework has already been deployed), allowing .NET applications to be deployed simply by copying the application files to their destination. This destination could be a network directory accessible by users who need to use the application.
However, there is one glitch in this scenario: .NET applications written to be deployed from a shared network drive should not rely on the registry for a couple of reasons:
- It simply goes against the idea of privatizing all parts of an application, and
- The app would have to use remote registry calls to make sure it writes to the registry of the server it resides on rather than the registry of the machine that invoked the app – at least for the application’s configuration data.
Fortunately, with extensive support for XML in the .NET libraries, it is fairly easy to write an XML based replacement for the registry. The
XmlRegistry class described here is one such implementation. The
XmlRegistryKey classes described here are modeled after the
RegistryKey classes in the .NET framework.
Internally, the classes use XML elements as the equivalent of sub-keys, and XML attributes as values.
One of the problems when writing to a document type store (as opposed to record oriented store such as a database or the registry), such as an XML file, is that the entire document needs to be saved even when a small part of the document is changed. Trying to optimize against this by minimizing the saves can be a hassle, and not optimizing has performance penalties that may be unacceptable.
XmlRegistry class (optionally) implements a Lazy Write mechanism to solve this problem: When a key is updated, a delayed save thread is started. The thread doesn’t save the file immediately, but instead first goes to sleep for a user specified time interval. During this sleep period, several other keys can be modified without causing the entire file to be saved each time. Eventually, the file is saved.
The registry is internally synchronized for conflicts between writes and delayed saves, however, it is not synchronized for multiple reader/writer threads. For such multithreaded use, the users should use their own locking mechanisms.
However, if the user doesn’t want to use the Lazy Write mechanism, they can simply use the
Save() member to explicitly save the file.
There are two classes that implement the XML registry:
XmlRegistryKey – modeled after the .NET
RegistryKey classes. To use this implementation, you would first instantiate an
XmlRegistry class object. Several constructors are available:
This is the simplest constructor. A file extension, if desired, must be part of the filename. If a file by the given name exists, it will be opened and the XML data read into memory. If the file doesn’t exist, an empty XML document with a root node called “root” will be created in memory – but not saved on disk.
XmlRegistry(string filename, string rootkeyname, string encoding)
This constructor allows the user to specify the root key name – for a blank document – and the XML encoding of the file. If a file already exists, its XML root element’s name must match
rootkeyname, otherwise an exception will be thrown.
public XmlRegistry(string filename, ErrorDelegate errhandler, int writedelay)
This constructor enables the Lazy Write feature, and allows you to specify the delay (in milliseconds).
public XmlRegistry(string filename, string rootkeyname, string encoding, ErrorDelegate errhandler, int writedelay)
This constructor also enables the Lazy Write feature, and in addition allows you to specify an asynchronous error-handling delegate. The delegate is called on the thread that saves the file, not the thread that made the registry call, so proper synchronization must be used in its implementation.
Regardless of whether the lazy write feature was enabled or not, this method will cause a file save to happen. If the lazy write feature was enabled, the save will happen on a separate thread, however the save delay would be cut short.
XmlRegistryKey XmlRegistryKey.GetSubKey(string path, bool createpath)
The path specified is a relative path, and sub-keys are separated by the ‘/’ character. For example, if the key referred to is ‘root/application’, and the method was called with the path argument equal to ‘configuration/cache’, the returned sub-key will refer to the full path of ‘root/application/configuration/cache’. The
createpath parameter specifies whether any missing elements of the path should be automatically created. If this is set to
false, and the full path does not exist, a null value will be returned.
XmlRegistry class is very straightforward:
XmlRegistry r1 = new XmlRegistry("Reg1.xml", null, 200);
XmlRegistryKey k1 = r1.RootKey;
XmlRegistryKey k2 = k1["abc/def/ghi", false];
XmlRegistryKey k3 = k1["a/bc/def/ghij/klmno", true];
XmlRegistryKey sk = k1.GetSubKeys();
foreach (XmlRegistryKey k in sk)
string name = k.Name;
This code snippet creates an XML file that appears as follows:
<klmno v1="0" v2="Hello" v3="True" />
This class is an easy way to handle registry-like issues in an XML file that can be local or placed on the server. Since it automatically creates the subkey structure, it is very easy to use.