Reputation: 301
Background: I'm using a Timer to do some work periodically within a Windows Service. I want the Timer to be configurable at run-time. The only thing I managed to do is configure it at startup.
My solution: I'm using app.config to configure start time and period of timer:
<appSettings>
<add key="StartTime" value="14:40:00"/>
<add key="Period" value="24:00:00"/>
</appSettings>
I'm using a FileSystemWatcher to notify of File Writes on the config file (will be AppName.exe.config)
public ConfigWatcher(params object[] args)
{
configurationChangedListeners = new List<INotifyConfigurationChanged>();
string assemblyDirectory = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
NotifyFilters notifyFilters = NotifyFilters.LastWrite;
_fileSystemWatcher = new FileSystemWatcher()
{
Path = assemblyDirectory,
NotifyFilter = notifyFilters,
Filter = "*.config"
};
_fileSystemWatcher.Changed += OnChanged;
_fileSystemWatcher.EnableRaisingEvents = true;
if (args != null)
{
foreach (var arg in args)
{
AddListener(arg);
}
}
}
private void OnChanged(object source, System.IO.FileSystemEventArgs e)
{
try
{
_fileSystemWatcher.EnableRaisingEvents = false;
ConfigurationManager.RefreshSection("appSettings");
foreach (var listener in configurationChangedListeners)
{
listener.NotifyConfigurationChanged();
}
}
finally
{
_fileSystemWatcher.EnableRaisingEvents = true;
}
}
Lastly, each listener is getting its configuration like so:
public void NotifyConfigurationChanged()
{
string strKeyName = "StartTime";
string startTime = ConfigurationManager.AppSettings[strKeyName];
// ...
}
And the problem: - When I edit the file, the File Watcher triggers the Event but when I try to get the new AppSettings I'm reading the OLD values (from when the service started)
The weird thing is, at some point this setup worked, and then it didn't (without changing code as far as I can tell).
Any help / suggestions are much appreciated.
Upvotes: 4
Views: 4114
Reputation: 1
Here's a simple answer:
private static ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
private static Configuration _config;
private static KeyValueConfigurationCollection _appSettings = null;
configMap.ExeConfigFilename = @"\Path\To\App.Config";
_config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
_appSettings = _config.AppSettings.Settings;
// Do your thing
_config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(_config.AppSettings.SectionInformation.Name);
It's the .Save that does the trick
Upvotes: 0
Reputation: 41
If you start your application in VS, make sure, that you edit right configuration file. I have spend few hours in order to catch that. Look:
While you debugging you execute (app_name).vshost.exe, if you want to update any key, you have to modify (app_name).vshost.exe.config as well!
Secondly,sectionName is CaseSeNsItIvE))
Perhaps for someone it will be helpful.
Upvotes: 4
Reputation: 301
The answer to the problem (after a lot of searching :D) was to use OpenExeConfiguration instead of directly accessing AppSettings. From what I understand, the config needs to be opened again after the refresh:
var appSettings = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetEntryAssembly().Location).AppSettings;
string setting = appSettings.Settings[strKeyName].Value;
I'm positive though that the first variant worked under a certain circumstance when I first tried it out...
Upvotes: 5