This article is also available as a TechRepublic download, which includes a complete Visual Studio 2005 project file with example code.

There
are many instances that require systems to perform certain tasks when files or
directories are created or modified. One example of this is an import system
that pulls flat files into a database. In this instance, a program must monitor
a directory for newly created files. When a file is created, the program must
pick up the file, parse it, and insert it into the database. Many times
this type of functionality is accomplished by “polling” the directory
and enumerating any new files that have been created since the last poll. With
the introduction of the .NET
Framework
, Microsoft has provided developers with an alternative to constantly polling a
directory for new files–the FileSystemWatcher object.

The FileSystemWatcher object does the work of monitoring
a directory for you. When a file is created, updated, or deleted, the FileSystemWatcher fires an event to notify you that a
change has occurred. This allows your program to know when a new file is
available almost immediately after the file is created. Immediate
notification of changes allows your system to work much more efficiently since
you’re not constantly polling the directory for changes, and there is no time
lapse between scans of the directory.

The FileSystemWatcher basics

There
are a few basic properties and events you need to familiarize yourself with before working with the FileSystemWatcher object. Undoubtedly, the most
important property of this object is the “EnableRaisingEvents” property. This property determines whether or
not the object will fire events when it receives a change notification. If EnableRaisingEvents is set to false, the object will
not fire the change events. If it is set to true, the events will be fired.
Below are several other important properties/events that you will use as you
take advantage of FileSystemWatcher:

Properties:

  • Path — This property tells the FileSystemWatcher which path it needs to
    monitor. For example, if we set this property to “C:\Temp\”, all
    changes in that directory would be monitored.
  • IncludeSubDirectoriesThis property indicates whether or not the FileSystemWatcher should monitor subdirectories for changes.
  • Filter — This property allows you to
    filter the changes for certain file types. For example, if we wanted
    to be notified only when TXT files are modified/created/deleted, we would set
    this property to “*.txt”. This property is very handy when
    working with high-traffic or large directories.

Events:

  • Changed — This event is fired when a file
    has been modified in the directory thatis being monitored. It is
    important to note that this event may be fired multiple times, even when
    only one change to the content of the file has occurred. This is due to
    other properties of the file changing as the file is saved.
  • Created — This event is fired when a file
    is created in the directory that is being monitored. If you are planning
    to use this event to move the file that was created, you must write some
    error handling in your event handler that can handle situations where the
    file is currently in use by another process. The reason for this is that
    the Created event can be fired before the process that created the file
    has released the file. This will cause exceptions to be thrown if you have
    not prepared the code correctly.
  • Deleted — This event is fired when a file
    is deleted in the directory that is being watched.
  • Renamed — This event is fired when a file
    is renamed in the directory that is being watched.

Note: None of these events will be fired
if you do not have EnableRaisingEvents set to true. If at any point your FileSystemWatcher does not seem to be working, check EnableRaisingEvents first to make sure it is set to
true.

Event processing

When
an event handler is called by the FileSystemWatcher, it contains two arguments–an object called “sender”,
and a FileSystemEventArgs object called “e”. The
argument we’re interested in is the FileSystemEventArgs argument. This object contains information about
what caused the event to be fired. The following is available from the FileSystemEventArgs object:

Properties:

  • Name — This property contains the
    name of the file that caused the event to be fired. It DOES NOT contain
    that path to the file–only the file or directory name that caused the
    event to be fired.
  • ChangeType — This is a type of WatcherChangeTypes
    and indicates which type of event was fired. Valid values are:
    • Changed
    • Created
    • Deleted
    • Renamed
  • FullPath — This contains the full path to the file that caused the
    event to fire. It includes the filename and the directory name.

Example code

Listing A is a simple example of how to use
the FileSystemWatcher. In this example we are watching
the “C:\Temp” directory for any *.TXT files that are created. This
is probably the simplest use of the FileSystemWatcher.

Listing A

publicvoid CreateWatcher()
{
//Create a new FileSystemWatcher.
FileSystemWatcher watcher = newFileSystemWatcher();

//Set the filter to only catch TXT files.
watcher.Filter = “*.txt”;

//Subscribe to the Created event.
watcher.Created += new
FileSystemEventHandler(watcher_FileCreated);

//Set the path to C:\Temp\
watcher.Path = @”C:\Temp\”;

//Enable the FileSystemWatcher events.
watcher.EnableRaisingEvents = true;
}

void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
//A new .TXT file has been created in C:\Temp\
Console.WriteLine(“A new *.txt file has been created!”);
}

Other examples are shown in the sample project included in
the download version of this article.

Uses

The
uses of the FileSystemWatcher may not be obvious at first.
Obviously, it will alert us that a file or directory has been modified, but in
what situations would that information be necessary?

One
situation where it could be used is in a system that allows clients to upload
files to be processed. While this is obviously the age of Web services and SOA,
many systems still work by being fed flat files to certain locations, whether
those locations are an FTP server or a network share. I have used the FileSystemWatcher for this type of system, and while
it’s not flawless, it certainly has its advantages over polling the directories
for new changes.

Another
situation where it could be used is if you want to keep two files in sync with
one another. You could use the FileSystemWatcher to monitor both file locations and fire a Changed event
when one of them is updated. You could then copy the changes over to the other
system/file.

If
your system has any functionality that requires files or directories to be
monitored, you should look closely at that component to see if the FileSystemWatcher could be of use. In my case, this
object saves at least 10 seconds on every file that is sent to the system.