Watching a Directory for Changes

A lot of my books have examples that require reliable access to one or more files on the hard drive. For example, the example showing how to load an XML file from disk on page 472 of C# Design and Development requires that the file is present—you can’t load a file that doesn’t exist. In fact, the need to know that a file is present is an overwhelming requirement in most of my books. For the most part, I can rely on the File.Exists() method to ensure that the file is there. If it isn’t, then I provide code to:

  • Rebuild the file
  • Use a backup file
  • Ask the user to supply the file
  • Create a new file from scratch.


I’m sure there must be other techniques in some of my books to handle the missing file, but the point is that when a file is missing, you have to deal with it in some way or the application will crash. A reader recently asked about an alternative to dealing with the missing filepreventing the user from deleting it in the first place (or at least logging the deletion). Sure, the user could attempt to delete the file, but a Windows service would sit in the background and place the file in a safe location for later retrieval. The suggestion has merit. It avoids the whole process of figuring out what to do now that the user has made life difficult.

I’ve written about working with Windows services in the past. In fact, it’s relatively easy to create a Windows service using Visual Studio. You can read about the process in my article entitled, “Writing a Managed Windows Service with C#.” However, that article doesn’t discuss how to monitor a directory so that you can detect a deletion and log the deletion as a minimum. So, that’s what I’ll discuss in the remainder of this post.

The FileSystemWatcher class provides the means to monitor file system changes and react to them. The concept is relatively simple. You create code that monitors the directories used by your application for changes. When a change occurs, you do something about it. I’ve created a very simple example to demonstrate the basics of what you need to do. Before you do anything else, add a reference to System.IO to your application.

Now that you have the required reference, let’s create a FileSystemWatcher. The first task is to initialize the object. I’ve created a simple button named btnStart to perform this task. The following code is a good starting place.

private void btnStart_Click(object sender, EventArgs e)
{
   if (btnStart.Text == "&Start")
   {
      // Keep an eye on C:\Temp.
      FSW = new FileSystemWatcher(@"C:\Temp");
 
      // Change the button text.
      btnStart.Text = "&Stop";
   }
   else
   {
      // Delete the existing FileSystemWatcher.
      FSW = null;
 
      // Change the button.
      btnStart.Text = "&Start";
   }
}

Unfortunately, this code won’t do much. Sure, it creates or destroys the FileSystemWatcher as needed, but it doesn’t really handle anything. To perform this next step, you need to create an event handler in the first part of the if statement. Since this reader is interested in deletions, you create a Deleted event handler by typing FSW.Deleted +=. When you type the =, the IDE automatically starts helping you create the required code. Press Tab to create the required FileSystemEventHandler object and then press Tab again to create the event handler, which is FSW_Deleted() in this case. Just to make things easy, the example displays a message box whenever the user deletes anything from C:\Temp. To make things symmetrical, you also have to remove the event handler in the second part of the if statement. The full code for this example then is:

// Create the FileSystemWatcher.
FileSystemWatcher FSW;
 
private void btnStart_Click(object sender, EventArgs e)
{
   if (btnStart.Text == "&Start")
   {
      // Keep an eye on C:\Temp.
      FSW = new FileSystemWatcher(@"C:\Temp");
 
      // Make sure that the FileSystemWatcher has events enabled.
      FSW.EnableRaisingEvents = true;
 
      // Change the button text.
      btnStart.Text = "&Stop";
 
      // Create a deleted event handler.
      FSW.Deleted += new FileSystemEventHandler(FSW_Deleted);
   }
   else
   {
      // Remove the event handler.
      FSW.Deleted -= FSW_Deleted;
 
      // Delete the existing FileSystemWatcher.
      FSW = null;
 
      // Change the button.
      btnStart.Text = "&Start";
   }
}
 
void FSW_Deleted(object sender, FileSystemEventArgs e)
{
   // Display a message box.
   MessageBox.Show("The user deleted: " + e.Name);
}

 

When you click Start, the application will monitor C:\Temp for any deleted files. Make sure that you set EnableRaisingEvents to true or the FileSystemWatcher won’t raise any events. When a deletion occurs, you see a message box telling you which file has been deleted. This solution is incomplete at the moment, but I plan to revisit it in the future. In the meantime, you have a tool now for knowing when a deletion has occurred that will affect the stability of your application so you can do something about it before the application crashes. Let me know if you have any questions at John@JohnMuellerBooks.com.