A useful feature supplied in .NET is the FileSystemWatcher object. If you need to know when changes are made to a directory (e.g. files being added, changed or deleted), this object allows you to capture an event describing what’s different just after the change is made.
Why is this useful?
There’s a number of scenarios – a couple are:
- You might want to audit changes made to a directory;
- After files are copied to a directory, you might want to automatically process them according to a property of that file (e.g. one user might be scanning files and saving those scans to a shared directory on your network, and this process could be processing files as they’re dropped into a directory by the scanner;
I’ve seen instances of where developers allow a user to upload a file through a website, and have lots of file processing code within their web application. One way to make the application cleaner would have been to separate out the file processing concern away from website.
How do you use it?
It’s pretty simple to use this class. I’ve written a sample program and pasted it below:
using System.IO; using static System.Console; using static System.ConsoleColor; namespace FileSystemWatcherSample { class Program { static void Main(string[] args) { // instantiate the object var fileSystemWatcher = new FileSystemWatcher(); // Associate event handlers with the events fileSystemWatcher.Created += FileSystemWatcher_Created; fileSystemWatcher.Changed += FileSystemWatcher_Changed; fileSystemWatcher.Deleted += FileSystemWatcher_Deleted; fileSystemWatcher.Renamed += FileSystemWatcher_Renamed; // tell the watcher where to look fileSystemWatcher.Path = @"C:\Users\Jeremy\Pictures\Screenshots\"; // You must add this line - this allows events to fire. fileSystemWatcher.EnableRaisingEvents = true; WriteLine("Listening..."); WriteLine("(Press any key to exit.)"); ReadLine(); } private static void FileSystemWatcher_Renamed(object sender, RenamedEventArgs e) { ForegroundColor = Yellow; WriteLine($"A new file has been renamed from {e.OldName} to {e.Name}"); } private static void FileSystemWatcher_Deleted(object sender, FileSystemEventArgs e) { ForegroundColor = Red; WriteLine($"A new file has been deleted - {e.Name}"); } private static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e) { ForegroundColor = Green; WriteLine($"A new file has been changed - {e.Name}"); } private static void FileSystemWatcher_Created(object sender, FileSystemEventArgs e) { ForegroundColor = Blue; WriteLine($"A new file has been created - {e.Name}"); } } }
Are there any problems?
Well maybe I wouldn’t call them problems, but there’s certainly a few things that surprised me when I was using this utility.
As an example, when I took a screenshot and saved to my Screenshots folder, I expected just one event to be called – the Created event. But the picture below shows all the events that actually were called.
Let’s look at what happens:
- First a file is created;
- Then it’s somehow changed three times;
- Then it’s renamed;
- Then another file is created, and changed;
- And finally, the original file is deleted.
This tells me something interesting about how my screenshot capture program works – but it also tells me to expect that the Created event will be fired twice when I take a single screenshot, so I’d have to code to prepare for that.
Ashutosh Nilkanth has blogged with another few tips and notes on using this class.
Summary
The FileSystemWatcher class is a useful .NET tool for observing changes to a directory structure. Because this watches for changes at an operating system level, events might be called in unexpected ways. Therefore it makes sense to properly understand the operating system events called when changes are made to the directory you’re monitoring, and design your solution to handle the real events (rather than the ones you might logically expect).