FileSystemWatcher class does not fire Change events when NotifyFilters.Size is used
Hi all,
A customer of mine was trying to monitor a .log file in a specific folder with .NET's FileSystemWatcher class and a code like the following:
static void Main(string[] args)
{
FileSystemWatcher fsw = new FileSystemWatcher(@"C:\mypath", "myfile.log");
fsw.NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite;
fsw.Changed += new FileSystemEventHandler(MyChangedMethod);
fsw.Error += new ErrorEventHandler(MyErrorMethod);
fsw.EnableRaisingEvents = true;
while (true)
;
}
static void MyErrorMethod(object sender, ErrorEventArgs e)
{
System.Console.WriteLine("Error= " + e.ToString());
}
static void MyChangedMethod(object sender, FileSystemEventArgs e)
{
FileInfo info = new FileInfo(e.FullPath);
System.Console.WriteLine("New size= " + info.Length + ". File= " + e.FullPath);
}
Another process was updating the .log file when it produced log messages.
A Changed event should be raised whenever the size of the specified file changes. This works on Windows XP/Server 2003. Now, on Windows Vista and later OS versions, this is not true.
The issue is caused by the second process updating the .log file with the Flush method, and a known limitation in this .NET method:
The Flush method of the FileStream class does not cause Windows to flush the file's metadata. This has the side-effect of not notifying any applications using FileSystemWatcher of file changes (writes) or LastWrite changes. The metadata is not flushed until the FileStream.Close method is called; at which time notifications are picked up by the native API ReadDirectoryChangesW used by FileSystemWatcher behind the scenes.
Now, why does it work on XP/Server 2003? Optimization took place on Vista/Server 2008 and later, and file notifications don’t come as regularly as before, only on close now. So if we don’t close the file , which Flush doesn’t do, we won't get the expected notifications.
The obvious workaround would be to close the file when you want FileSystemWatcher to get the event, and reopen it to continue writing.
Regards,
Alex (Alejandro Campos Magencio)
Comments
- Anonymous
May 16, 2011
This would be in my book, a bug in the Optimization in Windows 6.x. Flush should always force the update to the file system. Programmers use "Flush" to ensure the on-disk structures are updated.