Monitoring the File System – C#

You can use the FileSystemWatcher class to respond to file system events, such as a user creating, deleting, or removing a file. This might be useful if, for example, you wrote a program that automatically adds metadata to images copied to a particular folder, or automatically process text log files.

How to Monitor the File System

Responding to file system events requires three elements:

  • An instance of FileSystemWatcher configured with the properties to monitor
  • A method that runs when a change occurs
  • An event handler that specifies the method to run when the FileSystemWatcher event occurs

Once you have created these three elements, set FileSystemWatcher.EnableRaisingEvents to true to begin monitoring.

FileSystemMonitor Events

This table lists the three events you can respond to using the FileSystemWatcher class. You can create a single event handler for each of these types of events, and check the FileSystemEventArgs.ChangeType property in the event handler to determine the type of change event.

Event

Description

Changed Called when a new file is created, when a file is updated, or when a file’s attributes (other than its filename) are changed.
Renamed Called when a file is moved or renamed
Deleted Called when a file is removed from the file system
Created Called when a new file is added to the file system

Video Demonstration

In this video, I show you exactly how to use the FileSystemMonitor class using a WPF application. Be sure to watch it in HD, full-screen.


Here’s the transcript to that video:

To demonstrate the use of the FileSystemWatcher class, I’m going to create a WPF application that shows you any new pictures the user adds to their Pictures folder. First, I’m going to resize the window a bit so that it is more the shape of a normal picture, and I’ll give the window a name. Let’s call it MainWindow. Next, I’m going to go into the toolbox and drag over an Image control. I just want it to take up the entire MainWindow, so I’ll just remove the margins. Let’s call it updatedImage.

We want to create an event handler using the FileSystemWatcher class, which allows us to monitor a particular folder for changes. The FileSystemWatcher class is contained in the System.IO namespace, so I’ll add that now. First, I’ll need to identify the user’s Pictures folder. I’ll add it to a string called watchedFolder. I’ll use the Path.Combine method to concatenate the user profile folder, which is an environment variable, and the Pictures sub-folder. To get an environment variable, you call Environment.GetEnvironmentVariable. Then, I’ll specify the environment variable USERPROFILE. You can identify all environment variables at a command prompt by running the command SET.

Now I’m going to combine the user’s profile with the sub-folder Pictures, which in Vista is the subfolder for anyone’s pictures. Now I just need to create a FileSystemWatcher instance for that path. I’ll call it fsw, and I’ll provide the path as part of the constructor. To demonstrate how to interact with WPF controls, I’ll set the window’s title to the path that we’re monitoring. That way, the user will be able to see that we’re monitoring the correct folder.

FileSystemWatcher has a couple of properties that we want to specify. Often, if you’re unloading pictures from a camera, it will load it into sub-folders of the Pictures folder, so I want to make sure we monitor subfolders as well. I’ll set the IncludeSubdirectories property to true. I also want to set the NotifyFilters property so that updates are provided for a couple of different types of edits. You can see here that I can have it notify me about a couple of different properties of a file:

·         Attributes filters are triggered when a file’s attributes are edited.

·         CreationTime changes if someone manually went in and edited the creation time or if a new file were created.

·         DirectoryName would occur if a file was moved.

·         FileName would occur if a file were renamed.

·         LastAccess and LastWrite would trigger the filter if a file were updated.

·         If a file were appended or shortened, the Size property would change.

·         If a security descriptor were changed, the Security property would be used.

For me, I’m going to trigger on FileName and Last Write. That should be sufficient to notify me if a file is added.

Now that I’ve configured the FileSystemWatcher, I’m going to create a handler for the Changed event. You can see that in C# I specify it with the += operator. It provides me with a default handler—I just need to press Tab to insert it and it generates it for me. Again, it prompts me to press Tab to generate the event handler. I press Tab again, and I have an event handler.

Now I need to write the event handler; I can remove the default exception because I’m going to implement it now.

There’s a trick I need to explain. I’m need to display the updated picture in this control, however, when you’re handling events in a WPF application, the event handler is in a different thread. That means that I don’t have direct access to the controls in the window. So, I could write this command and specify the path of the updated file, but it won’t work—I would get an exception because I don’t have access to the controls in the WPF window. What I need to do instead is to use the dispatcher.

You can see that I have access to the updatedImage control. I call the Dispatcher.Invoke command which takes two parameters—a Priority, and then an Action. I use the System.Windows.Threading.DispatcherPriority to specify the priority of the dispatcher—Normal is fine. Then, I specify an Action by typing New Action.

Within this delegate I’m going to specify the changes that I want to make. First, I’m going to create an ImageSourceConverter instance, which is required to specify the source of the updated Image control. You can’t simply provide a Source of a file path, so the ImageSourceConverter converts from the file path to the Source in the format that it’s required.

Now that I’m within the delegate in the dispatcher, I can access updatedImage.Source, cast it to ImageSource, and call the ImageSourceConverter.ConvertFromString method.

This is almost ready to go—I have one more change I need to make. I need to set the FileSystemWatcher.EnableRaisingEvents to true, otherwise events won’t fire. This is ready to run now.

There’s my picture window. I’ll expand that a little bit. Now, let me pull up my Pictures folder. You can see I have some vacation photos. I will simply copy one of these folders to the same folder, and you can see that the WPF application detects the change, finds the full path to the file, and displays it in the image folder. I can do this repeated times with the same result.

Now, I want to demonstrate within the event handler how it found the folder path. Notice that the event handler, which was automatically generated by C#, takes two parameters: the sender object, which I don’t access (and I don’t need to access, typically) and the FileSystemEventArgs instance. Almost all event handlers have some derivative of EventArgs, and the default code generated by Visual Studio always calls it e. So, e has a variety of useful parameters here, and they’re specific to the event that’s being thrown. In this case, the FileSystemWatcher event wants to let me know the file that was changed and what type of change happened to it. You can see that it has three properties here: ChangeType, which specifies whether the file was changed or renamed, FullPath, which is the full path to the file, and Name, which is just the filename. When I specified the path to the picture, I used the FileSystemEventArgs.FullPath property, sent it to the ImageSourceConverter, and then cast that to ImageSource.

FileSystemMonitor Sample Project Source Code

Download the WPF FileSystemMonitor sample project: WPF Monitoring Sample Solution in C#.

Return to the .NET Framework Fundamentals Tutorials Table of Contents.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>