Posted by Marco Minerva
Some times ago I published a class that allows to read XML Configurtion Files (.config) in the standard .NET format. Now, I am asked how to change and save these settings back to file.
So, I have updated the ConfigurationManager class to support these new features.
public static class ConfigurationManager { private const string APPSETTINGS_SECTION = "appSettings"; private const string ADD = "add"; private const string KEY = "key"; private const string VALUE = "value"; private static Hashtable appSettings; static ConfigurationManager() { appSettings = new Hashtable(); } public static string GetAppSetting(string key) { return GetAppSetting(key, null); } public static string GetAppSetting(string key, string defaultValue) { if (!appSettings.Contains(key)) return defaultValue; return (string)appSettings[key]; } public static void SetAppSetting(string key, string value) { appSettings[key] = value; } public static void Load(Stream xmlStream) { appSettings.Clear(); using (XmlReader reader = XmlReader.Create(xmlStream)) { while (reader.Read()) { switch (reader.Name) { case APPSETTINGS_SECTION: while (reader.Read()) { if (reader.Name == APPSETTINGS_SECTION) break; if (reader.Name == ADD) { var key = reader.GetAttribute(KEY); var value = reader.GetAttribute(VALUE); //Debug.Print(key + "=" + value); appSettings.Add(key, value); } } break; } } } } public static void Save(Stream xmlStream) { using (StreamWriter writer = new StreamWriter(xmlStream)) { writer.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>"); writer.WriteLine("<configuration>"); writer.WriteLine("\t<appSettings>"); foreach (DictionaryEntry item in appSettings) { string add = "\t\t<add key=\"" + item.Key + "\" value=\"" + item.Value + "\" />"; writer.WriteLine(add); } writer.WriteLine("\t</appSettings>"); writer.WriteLine("</configuration>"); } } }
There are two new methods: SetAppSetting and Save. The former is used to add settings and modify existing ones, while the latter saves the configuration file (tipically on a SD card). To write the file, we use a StreamWriter to create the XML based on the hastable contents.
Its usage is very simple. Create a new .NET Gadgeteer application and connect the SD Card and a button module to the FEZ Spider. In the root of the SD Card, put the following configuration file with the name Application.config:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSetting> <add key="Key1" value="Value1" /> <add key="Key2" value="Value2" /> <add key="Key3" value="Value3" /> <add key="hostName" value="www.google.it" /> <add key="port" value="25" /> </appSettings> </configuration>
Finally, in the Program.cs file, we write the code to use the ConfigurationManager class.
using System; using System.Collections; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.Presentation; using Microsoft.SPOT.Presentation.Controls; using Microsoft.SPOT.Presentation.Media; using Microsoft.SPOT.Touch; using Gadgeteer.Networking; using GT = Gadgeteer; using GTM = Gadgeteer.Modules; using Gadgeteer.Modules.GHIElectronics; using System.IO; namespace AppSettingsRWExample { public partial class Program { private const string FILE_PATH = "Application.config"; // This method is run when the mainboard is powered up or reset. void ProgramStarted() { sdCard.SDCardMounted += new SDCard.SDCardMountedEventHandler(sdCard_SDCardMounted); button.ButtonPressed += new Button.ButtonEventHandler(button_ButtonPressed); Debug.Print("Program Started"); } private void sdCard_SDCardMounted(SDCard sender, GT.StorageDevice SDCard) { // Reads configuration file. using (Stream configStream = SDCard.OpenRead(FILE_PATH)) { // Loads settings. ConfigurationManager.Load(configStream); } // Retrieves some values. var host = ConfigurationManager.GetAppSetting("HostName"); var port = ConfigurationManager.GetAppSetting("Port"); var userName = ConfigurationManager.GetAppSetting("Username", "anonymous"); Debug.Print("HostName: " + host); Debug.Print("Port: " + port); Debug.Print("Username: " + userName); } private void button_ButtonPressed(Button sender, Button.ButtonState state) { // Changes an existing value in the file. ConfigurationManager.SetAppSetting("HostName", "http://www.netmf.com/gadgeteer"); // Adds a value that contains the last save time. ConfigurationManager.SetAppSetting("LastSaveTime", DateTime.Now.ToString()); // Saves settings. using (Stream configStream = sdCard.GetStorageDevice().OpenWrite(FILE_PATH)) { ConfigurationManager.Save(configStream); } Debug.Print("Settings saved"); } } }
In this code, we read configuration settings when the memory card in inserted into the module, as described in the previous post. Then, when we press the button, the button_Pressed event is raised. First al all, we use the new SetAppSetting method: we overwrite a value (HostName) that already exsits and add a new one (LastSaveTime). Finally, we invoke the Save method, passing the stream that represents the file in which to write all the settings.
This application is available for download.
#1 by JayJay on March 25, 2012 - 8:51 AM
Thank you for the new updated config class….
Awesom…
#2 by Marco Minerva on March 25, 2012 - 8:54 AM
Thank you too for the comment!
#3 by Craig on September 30, 2013 - 3:34 AM
thanks for the class, note you have a typo on the appsettings section of the config file “appSetting” should be “appSettings”
#4 by Alan Hartmann on March 13, 2014 - 2:16 PM
Thanks, this was a big help!