Is there an easier way to extract nodes from an App Config File than using the IConfigurationSectionHandler Interface? It seems a little cumbersome to simply retrieve one node from the AppConfig file. Yes, there is a simple way to do it. In this article I will demonstrate a small wrapper class that I have written for the XmlDocument object.
I originally was using the IConfigurationSectionHandler Interface to write a ConfigurationHandler Class, but found it a little cumbersome, seeing that the AppConfig file itself has to be modified to facilitate the use of the IConfigurationSectionHandler Interface.
The Wrapper class that I have written will, by default, load the application's config file, or alternately load any XML file passed as a parameter to the constructor. Once the constructor is called, you then call the GetSingleNode method to retrieve the inner text of an XML node. You must pass the completely qualified node whose value you want to retrieve. Figure 1 demonstrates the calling code to the wrapper class. I am using this code, first to get the path to AppStart.exe.Config, which is the shim application for the Updater Application Block. I then read it to get the path to the current version of a self updating application.
Figure 1 - Calling the Wrapper.
| // first we get the path to the appStart.exe.config // it has already been modified by the upadter to point // to the new exe path. Passing an empty string will // cause the wrapper to default to the current app config file xCH = new XMLConfigurationHandler(""); // next line returns // "C:\Self Updating Application\DemoApp\AppStart.exe.config" string appStartConfig = xCH.GetSingleNode( "configuration/appUpdater/UpdaterConfiguration/application/client/xmlFile"); // Next, I want to get the path to the current self updating application // so I create a new instance of the wrapper passing the path // retrieved in the last call. xCH = new XMLConfigurationHandler(appStartConfig); // returns "C:\Self Updating Application\DemoApp\2.0.0.0" string newVersionAppPath = xCH.GetSingleNode( "configuration/appStart/ClientApplicationInfo/appFolderName"); string pathToAppStartConfigFile = Path.Combine(myPath,"AppStart.exe.config"); if (!xCH.ReplaceSingleNodeValue(xPathToxmlFile ,pathToAppStartConfigFile)) return false; |
| <xmlFile>C:\Self Updating Application\DemoApp\2.0.0.0</xmlFile> |
| <xmlFile>filePath = "C:\Self Updating Application\DemoApp\1.0.0.0" appName = "Test.exe"</xmlFile> |
| <logListener logPath = "C:\Self Updating Application\DemoApp\1.0.0.0\UpdaterLog.txt" /> |
| <logListener logPath = "C:\Program Files\MyApp\UpdaterLog.txt" /> |
| string xPath = "configuration/appUpdater/UpdaterConfiguration/application/client/@logPath"; |
| string logPath = Path.Combine(myPath, "UpdaterLog.txt"); if (!xCH.ReplaceSingleNodeValue(xPathToLogListener, logPath)) return false; |
| <logListener logPath = "C:\Program Files\MyApp\UpdaterLog.txt" /> |
| using System; using System.Xml; namespace InfoPro.UABWrapper { /// <summary> /// This is a simple class wrapper for the xml document object. /// It allow reading and updating the innertext of a single node /// that can be specified by an xPath to the node. If no file is /// passed to the constructor, the appConfig file will be loaded. /// Passing a filename of an xml file will load that file. /// public class XMLConfigurationHandler { #region Class Level Variables & Properties private XmlDocument _doc; private string _XmlFileName; public string XmlFileName { get{return _XmlFileName;} set{_XmlFileName = value;} } public XmlDocument doc { get{return _doc;} set{_doc = value;} } #endregion #region Constructor /// <summary> /// Load the app config file for this app /// if xmlFile is empty, otherwise load /// xmlFile. If there is no valid file, the constructor will /// cause an unhandled exception. /// /// public XMLConfigurationHandler(string xmlFile) { doc = new XmlDocument(); if(xmlFile==string.Empty) { doc.Load( AppDomain.CurrentDomain.SetupInformation.ConfigurationFile ); XmlFileName = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; } else { doc.Load(xmlFile); XmlFileName = xmlFile; } } #endregion #region Public Methods /// <summary> /// Return inner text of node specified by xPath. /// If xPath is not valid, a null reference exception /// will be generated on the call to SelectSingleNode. /// /// /// <returns> public string GetSingleNode(string xPath) { try { string innerText = doc.SelectSingleNode(xPath).InnerText; return innerText; } catch(System.Exception ex) { return string.Empty; } } /// <summary> /// This method will replac the text into the xml document /// for the node(xPath) passed. /// If xPath is not valid, a null reference exception /// will be generated on the call to SelectSingleNode. /// /// /// /// <returns> public bool ReplaceSingleNodeValue(string xmlPath, string text) { try { System.Xml.XmlNode node = doc.SelectSingleNode(xmlPath); node.InnerText = text; doc.Save(XmlFileName); return true; } catch { return false; } } #endregion } } |