I'd like to re-read the MySolution.main.config (my app.config) thanks FileSystemWatcher when users modify it. I built a wrapper called FileWatcher.
Catching OnChanged event with this piece of code
var map = new ExeConfigurationFileMap { ExeConfigFilename = _appConfigFilePath };
var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
raises this exception
System.Configuration.ConfigurationErrorsException HResult=0x80131902 Message=An error occurred loading a configuration file: The process cannot access the file 'C:\Source\Solutions\MySolution_1.2.3\MySolution\bin\Debug\MySolution.main.config' because it is being used by another process. (C:\Source\Solutions\MySolution_1.2.3\MySolution\bin\Debug\MySolution.main.config) Source=System.Configuration.ConfigurationManager StackTrace: at System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean ignoreLocal) in //src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationSchemaErrors.cs:line 71 at System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors(ConfigurationSchemaErrors schemaErrors) in //src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/BaseConfigurationRecord.cs:line 3634 at System.Configuration.Configuration..ctor(String locationSubPath, Type typeConfigHost, Object[] hostInitConfigurationParams) in //src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/Configuration.cs:line 75 at System.Configuration.ClientConfigurationHost.OpenExeConfiguration(ConfigurationFileMap fileMap, Boolean isMachine, ConfigurationUserLevel userLevel, String exePath) in //src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigurationHost.cs:line 485 at System.Configuration.ConfigurationManager.OpenExeConfigurationImpl(ConfigurationFileMap fileMap, Boolean isMachine, ConfigurationUserLevel userLevel, String exePath, Boolean preLoad) in //src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationManager.cs:line 214 at System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap, ConfigurationUserLevel userLevel) in //src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ConfigurationManager.cs:line 192 at Siav.MySolution.Log.ConfigurationUtil.FileWatcher.OnChanged(Object sender, FileSystemEventArgs e) in C:\Source\Solutions\MySolution_1.2.3\Siav.MySolution.Log\ConfigurationUtil\FileWatcher.cs:line 60 at System.IO.FileSystemWatcher.OnChanged(FileSystemEventArgs e) in f:\dd\NDP\fx\src\services\io\system\io\FileSystemWatcher.cs:line 822 at System.IO.FileSystemWatcher.NotifyFileSystemEventArgs(Int32 action, String name) in f:\dd\NDP\fx\src\services\io\system\io\FileSystemWatcher.cs:line 773
at System.IO.FileSystemWatcher.CompletionStatusChanged(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* overlappedPointer) in f:\dd\NDP\fx\src\services\io\system\io\FileSystemWatcher.cs:line 594
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP) in f:\dd\ndp\clr\src\BCL\system\threading\overlapped.cs:line 121This exception was originally thrown at this call stack: System.IO.__Error.WinIOError(int, string) in __error.cs System.IO.FileStream.Init(string, System.IO.FileMode, System.IO.FileAccess, int, bool, System.IO.FileShare, int, System.IO.FileOptions, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES, string, bool, bool, bool) in filestream.cs System.IO.FileStream.FileStream(string, System.IO.FileMode, System.IO.FileAccess, System.IO.FileShare) in filestream.cs System.Configuration.Internal.InternalConfigHost.StaticOpenStreamForRead(string) in InternalConfigHost.cs System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigHost.OpenStreamForRead(string) in InternalConfigHost.cs System.Configuration.ClientConfigurationHost.OpenStreamForRead(string) in ClientConfigurationHost.cs System.Configuration.UpdateConfigHost.OpenStreamForRead(string) in UpdateConfigHost.cs System.Configuration.ImplicitMachineConfigHost.OpenStreamForRead(string) in ImplicitMachineConfigHost.cs System.Configuration.BaseConfigurationRecord.InitConfigFromFile() in BaseConfigurationRecord.cs
Inner Exception 1: IOException: The process cannot access the file 'C:\Source\Solutions\MySolution_1.2.3\MySolution\bin\Debug\MySolution.main.config' because it is being used by another process.
I tried with a simple lock, it doesn't work.
This is the constructor of my wrapper
public FileWatcher(string appConfigFilePath)
{
_appConfigFilePath = appConfigFilePath;
_lastRead = DateTime.MinValue;
var watcher = new FileSystemWatcher(Path.GetDirectoryName(_appConfigFilePath))
{
Filter = Path.GetFileName(_appConfigFilePath),
NotifyFilter = NotifyFilters.LastWrite,
EnableRaisingEvents = true
};
watcher.Changed += OnChanged;
watcher.Error += OnError;
}
Any suggestions?
Thanks
I had to manage some retry to access the file as log4net does. I suggest to you to do the same (log4net source is available on github)