title: Using FileSystemMonitoring for reading changes in app.config and writing to app.config realtime
body: <p>I am using FileSystemWatcher to monitor any changes in the app.config file. And also, writing to the config file. </p>
  
  <p>Here is my code : </p>
  
  <p>MyApplication is the main project and DataCache is a clas library referenced in MyApplication. </p>
  
  <pre><code>using System;
  using System.Threading;
  using System.IO;
  namespace MyApplication
  {  
  
    public class Program
    {
      public static string rootFolderPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
      public static string configFilePath = Path.Combine(rootFolderPath, "MyApplication.exe.config");static void Main(string[] args)
      {
          //First Time initializing the config file.
          ConfigFileMonitor.SetConfigFileAtRuntime(configFilePath);
  
          //Initializing the config file monitor on a separate thread.
          Thread monitorThread = new Thread(ConfigFileMonitor.BeginConfigFilesMonitor);
          monitorThread.Start();
  
          WriteToConfigFile();
  
      }
  
      static void WriteToConfigFile()
      {
          Console.WriteLine(String.Format("Hello {0} {1}", DataCache.Section1Data.FirstNameString, DataCache.Section1Data.LastNameString));
  
          string _firstName, _lastName = string.Empty;
          do
          {
              Console.WriteLine("");
              Console.Write("First Name : ");
              _firstName = Console.ReadLine();
  
              Console.Write("Last Name : ");
              _lastName = Console.ReadLine();
  
              if(_firstName.Length&gt;0)
                  DataCache.Section1Data.FirstNameString = _firstName;
  
              if(_lastName.Length&gt;0)
                  DataCache.Section1Data.LastNameString = _lastName;
  
              Console.WriteLine(String.Format("Hello {0} {1}", DataCache.Section1Data.FirstNameString, DataCache.Section1Data.LastNameString));
          }
          while (true);
      }
    }
  }
  
  
  using System;
  using System.IO;
  
  namespace MyApplication
  {
      /// &lt;summary&gt;
      /// Monitors for any change in the app.config file
      /// &lt;/summary&gt;
      public class ConfigFileMonitor
      {
           private static FileSystemWatcher _watcher;
           private static string _configFilePath = String.Empty;
           private static string _configFileName = String.Empty;
  
          /// &lt;summary&gt;
      /// Texts the files surveillance.
      /// &lt;/summary&gt;
      public static void BeginConfigFilesMonitor()
      {
          try
          {
              string fileToMonitor = Program.configFilePath;
              if (fileToMonitor.Length == 0)
                  Console.WriteLine("Incorrect config file specified to watch");
              else
              {
                  _configFileName = Path.GetFileName(fileToMonitor);
                  _configFilePath = fileToMonitor.Substring(0, fileToMonitor.IndexOf(_configFileName));
              }
              // Use FileWatcher to check and update only modified text files.
              WatchConfigFiles(_configFilePath, _configFileName);
          }
          catch (Exception e1)
          {
              Console.WriteLine(e1.Message);
          }
      }
  
      /// &lt;summary&gt;
      /// Watches the files.
      /// &lt;/summary&gt;
      /// &lt;param name="targetDir"&gt;The target dir.&lt;/param&gt;
      /// &lt;param name="filteredBy"&gt;The filtered by.&lt;/param&gt;
      static void WatchConfigFiles(string targetDir, string filteredBy)
      {
          try
          {
              _watcher = new FileSystemWatcher();
              _watcher.Path = targetDir;
              _watcher.Filter = filteredBy;
              _watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite;
              _watcher.EnableRaisingEvents = true;
  
              _watcher.Changed += new FileSystemEventHandler(FileChanged);
              _watcher.WaitForChanged(WatcherChangeTypes.Changed);
          }
          catch (Exception e1)
          {
              Console.WriteLine(e1.Message);
          }
      }
  
  
      /// &lt;summary&gt;
      /// Handles the Changed event of the File control.
      /// &lt;/summary&gt;
      /// &lt;param name="sender"&gt;The source of the event.&lt;/param&gt;
      /// &lt;param name="e"&gt;The &lt;see cref="System.IO.FileSystemEventArgs"/&gt; instance containing the event data.&lt;/param&gt;
      protected static void FileChanged(object sender, FileSystemEventArgs e)
      {
          try
          {
              _watcher.EnableRaisingEvents = false;
  
              string filechange = e.FullPath;
  
              Console.WriteLine("Configuration File: " + filechange + "changed");
  
              //Since the file is changed - We have reload the configuration settings again.
              SetConfigFileAtRuntime(Path.Combine(Program.rootFolderPath, "MyApplication.exe.config"));
  
              Console.WriteLine(String.Format("New Name : {0} {1}", DataCache.Section1Data.FirstNameString, DataCache.Section1Data.LastNameString));
  
          _watcher.EnableRaisingEvents = true;
          }
          catch (Exception e1)
          {
              Console.WriteLine(e1.Message);
          }
      }
  
      /// &lt;summary&gt;
      /// Sets the config file at runtime.
      /// &lt;/summary&gt;
      /// &lt;param name="configFilePath"&gt;&lt;/param&gt;
      public static void SetConfigFileAtRuntime(string configFilePath)
      {
          string runtimeconfigfile;
          try
          {
              if (configFilePath.Length == 0)
                  Console.WriteLine("Please specify a config file to read from ");
              else
              {
                  runtimeconfigfile = configFilePath;
                  _configFileName = Path.GetFileName(configFilePath);
                  _configFilePath = configFilePath.Substring(0, configFilePath.IndexOf(_configFileName));
              }
  
              // Specify config settings at runtime.
              //System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
              DataCache.DataConfigSection.config = System.Configuration.ConfigurationManager.OpenExeConfiguration(configFilePath);
              //Similarly you can apply for other sections like SMTP/System.Net/System.Web etc..
              //But you have to set the File Path for each of these
              //config.AppSettings.File = runtimeconfigfile;
  
              //This doesn't actually going to overwrite you Exe App.Config file.
              //Just refreshing the content in the memory.
              DataCache.DataConfigSection.config.Save(System.Configuration.ConfigurationSaveMode.Modified);
  
              //Refreshing Config Section
              //ConfigurationManager.RefreshSection("appSettings");
              System.Configuration.ConfigurationManager.RefreshSection("MySectionGroup/Section1");                
  
              DataCache.Section1Data.configSection1 = null;
          }
          catch (Exception e1)
          {
              Console.WriteLine(e1.Message);
          }
      }
   }
  }
  
  &lt;?xml version="1.0"?&gt;
  &lt;configuration&gt;
    &lt;configSections&gt;
      &lt;sectionGroup name="MySectionGroup"&gt;
        &lt;section name="Section1"  type="DataCache.DataConfigSection, DataCache"     allowLocation="false" allowDefinition="Everywhere"/&gt;
        &lt;section name="Section2"  type="DataCache.DataConfigSection, DataCache"     allowLocation="false" allowDefinition="Everywhere"/&gt;
      &lt;/sectionGroup&gt;
    &lt;/configSections&gt;
    &lt;MySectionGroup&gt;
      &lt;Section1&gt;
        &lt;name
          firstName ="Pierce"
          lastName ="Brosnan"
          /&gt;
      &lt;/Section1&gt;
    &lt;/MySectionGroup&gt;
  
  &lt;startup&gt;&lt;supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/&gt;
  &lt;/startup&gt;
  
  &lt;/configuration&gt;
  </code></pre>
  
  <p>Here are the DataCache classes : </p>
  
  <pre><code>using System;
  namespace DataCache
  {
      public sealed class DataConfigSection : System.Configuration.ConfigurationSection
      {
          public static System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(
          System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetAssembly(typeof(DataConfigSection)).Location), "MyApplication.exe"));
  
      // Create a "name" element.
      [System.Configuration.ConfigurationProperty("name")]
      public NameElement Name
      {
          get
          {
              return (NameElement)this["name"];
          }
          set
          {
              this["name"] = value;
          }
      }
  
      // Define the "name" element
      // with firstName, secondName attributes.
      public class NameElement : System.Configuration.ConfigurationElement
      {
          [System.Configuration.ConfigurationProperty("firstName", DefaultValue = "abcd", IsRequired = true)]
          public String FirstName
          {
              get
              {
                  return (String)this["firstName"];
              }
              set
              {
                  this["firstName"] = value;
              }
          }
  
          [System.Configuration.ConfigurationProperty("lastName", DefaultValue = "xyz", IsRequired = true)]
          public String LastName
          {
              get
              {
                  return (String)this["lastName"];
              }
              set
              {
                  this["lastName"] = value;
              }
          }
      }
    }
  }
  
  
  namespace DataCache
  {
      public class Section1Data
      {
          public static volatile DataConfigSection configSection1;
          private static object syncRoot = new System.Object();
  
      public const string Section1ConfigSectionName = "MySectionGroup/Section1";
  
      private Section1Data() { }
  
      public static DataConfigSection ConfigSection1
      {
          get
          {
              lock (syncRoot)
              {
                  if (configSection1 == null)
                  {
                      DataConfigSection.config = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetAssembly(typeof(DataConfigSection)).Location), "MyApplication.exe"));
                      configSection1 = (DataConfigSection)DataConfigSection.config.GetSection(Section1ConfigSectionName);                   
                  }
              }
              return configSection1;
          }
      }
      public static string FirstNameString
      {
          get
          {
              return ConfigSection1.Name.FirstName.ToString();
          }
          set
          {
              ConfigSection1.Name.FirstName = value;
              DataConfigSection.config.Save();
          }
      }
      public static string LastNameString
      {
          get
          {
              return ConfigSection1.Name.LastName.ToString();
          }
          set
          {
              ConfigSection1.Name.LastName = value;
              DataConfigSection.config.Save();
          }
      }
    }
  }
  </code></pre>
  
  <p>The issue is if there is any change made to the name from console input, FileChanged gets called once and subsequent changes do not fire it. Moreover, if changes are made manually to the config file, it works fine till and events keep firing till a change is made from console. </p>
  
  <p>I am not sure why is this behaving weird. Can anyone help me here. </p>
  
  <p>Thanks,
  Monica </p>