
.NET 1.1+Detecting File Changes with FileSystemWatcher (2)
If you are developing a Windows Explorer-style application or integrating with a legacy or third-party system that can only provide information via files, you may need to monitor the files within a folder. The FileSystemWatcher class permits this.
Preventing Cross-Thread Operations
By default, when the FileSystemWatcher object raises notification events, the delegate calls are made on a thread from the system thread pool. This will generally not be the same thread as that being used to control the form. As the demonstration application will require that the file changes be logged within a visual element of the form, using the allocated thread to modify the list box contents would result in a cross-threading operation and an IllegalOperationException being thrown.
To force the FileSystemWatcher to use the thread that the form is operating under and to avoid errors, the SynchronizingObject property can be used. This property will be set to the form's class so that the form object is used to marshal the event handler calls. To set this property, modify the form's constructor as follows:
public FileMonitorForm()
{
InitializeComponent();
_watcher = new FileSystemWatcher();
_watcher.SynchronizingObject = this;
}
Trapping the File Change Events
The FileSystemWatcher raises four events in response to changes in the monitored folder. These provide information for file and folder creation, modification, deletion and renaming. The first three of these are based on the FileSystemEventHandler delegate. This delegate includes a FileSystemEventArgs parameter that provides information relating to the path and name of the file or folder modified.
The Renamed event is based on the RenamedEventHandler delegate. This delegate provides a RenamedEventArgs object with information describing the activity that occurred. The RenamedEventArgs class is derived from FileSystemEventArgs but adds extra properties to hold the old name of the file or folder.
To attach to the four events in the sample application, add the following four lines to the end of the constructor:
_watcher.Changed += new FileSystemEventHandler(LogFileSystemChanges);
_watcher.Created += new FileSystemEventHandler(LogFileSystemChanges);
_watcher.Deleted += new FileSystemEventHandler(LogFileSystemChanges);
_watcher.Renamed += new RenamedEventHandler(LogFileSystemRenaming);
We now need to create two methods to process the notifications. The first method will handle the Changed, Created and Deleted events. In each case, the information from the event arguments will be logged in the list box. The list will display the time of the change, the name of the file affected and the type of change that occurred.
Add the following method to log the changes. The log text is created using the String.Format method with the {0:G} placeholder indicating that the current date and time will be formatted using the user's preferred short date format and long time format. The FullPath property returns the full path of the changed file. The ChangeType property returns a value from the WatcherChangeTypes enumeration that is automatically converted to a readable string by the Format method.
void LogFileSystemChanges(object sender, FileSystemEventArgs e)
{
string log = string.Format("{0:G} | {1} | {2}", DateTime.Now, e.FullPath, e.ChangeType);
ChangeLogList.Items.Add(log);
}
The second method to add will process the event raised when a file or folder is renamed. This method is similar to the previous one except that the change type is always "Renamed". We will log the old name and new path and name for the changed item.
Add the following method to log renaming:
void LogFileSystemRenaming(object sender, RenamedEventArgs e)
{
string log = string.Format("{0:G} | {1} | Renamed from {2}", DateTime.Now
, e.FullPath, e.OldName);
ChangeLogList.Items.Add(log);
}
22 March 2008