Monday, September 17, 2012

[ C# ] - Monitor File System Recursively using FileSystemWatcher component

1. Introduction to FileSystemWatcher

"FileSystemWatcher Component" will track the changes in the file system. The changes include file creation, deletion, Modification and renaming a file. In this article, we will create a sample that can spy on your file system based on the folder path that you specify.

Whenever a change is encountered in the file system, it notifies the listening application through the events like File changed.

2. About the File System Monitor Sample

The below screenshot shows the sample application:


Figure 1. Sample Application


The top screen will show the Spied content. This wide white screen is a multi-line text box. Folder Picker button will enable you to pick a folder path to be monitored. Once a folder is picked, the folder name will be displayed in the Folder Path to Monitor text box. The Recursive check box tells that we want to monitor the sob-folders of the folder picked by the folder picker dialog. Say, for example, if we picked C:\ through folder picked and checked the Recursive checkbox, then the entire C:\ partition or drive will be monitored.

Start Monitor button will start the monitoring process. There is no much validation done here, so the sequence is:


  1.     Specify the Folder path to monitor
  2.   If you want to monitor recursively, place a check mark on the Recursive checkbox
  3.     Decide the kind of action
  4.     Then click the monitor button

Clear Content button will erase the spied content displayed on the output screen at any time. Close button… Do you need an explanation for it? The four checkbox filters are useful for specifying what kind of action you want to track. It is simple to create this sample as much of the work is done by the component.


3. Preparing the Form for FileSystemWatcher Example

From fig.1 you can easily place the required controls to the form. I used basic only basic controls in the form. So it is not a big deal to design such form. To prepare the sample we need two components. One is "FolderBrowserDialog Component" and the another one is "FileSystemWatcher Component". FileSystemWatcher is the key component that is going to spy the file system on the folder that you specify. Fig.2 shows from where you can drag drop these components.

Figure 2. Components required


In our sample, FolderB is the name given to the FolderBrowserDialog and FileMon is the name given to the FileSystemWatcher component. Once the components are dropped, we need to provide four events handler for the FileSystemWatcher (FileMon) component dropped on the form. Fig.3 shown below describes the event handler provided for the FileMon.


Figure 3. FileSystemWatcher Events




4. Source Code Explanation

1) First, the required variables are declared. We will see the use of it when we progress through the coding.

//Sample 01: Declarations.
private string content = "";
private string last_event_filename = "";

2) Event handler provided for the close and Clear Content is straightforward. The code for that is given below:

//Sample 02: Close the form
private void btnClose_Click(object sender, EventArgs e)
{
    fileMon.EnableRaisingEvents = false;
    this.Close();
}
//Sample 03: Clear Text Content
private void btnClear_Click(object sender, EventArgs e)
{
    txtDisplay.Clear();
}  

3) The FileSystemWatcher component will spy the files under a given path. To spy the files inside the sub-folder we should set "IncludeSubdirectories Property" to true. We can set this property only when we have a valid path and it is set through the Path property. In our sample, we provided a checkbox that will set IncludeSubdirectories property to true or false based on its check state. Below is the code:

//Sample 04: Do it recursively
private void chkRecursive_CheckedChanged(object sender, EventArgs e)
{
    if (chkRecursive.Checked == true )
        fileMon.IncludeSubdirectories = true;
    else
        fileMon.IncludeSubdirectories = false;
}

4) In the previous step we shown the code that set the IncludeSubdirectories and this property of the component become meaningful only when we have a valid path to monitor. The "Path Property" of the component will be used to specify from where exactly we want to monitor the files. To set this Path property, we used FolderBrowserDialog component from the dialogs group. When the … button is clicked, we make use of the folder browser dialog to read the Folder Path to monitor from the user of the sample. And the Recursive checkbox will tell we need to monitor this selected path recursively or not. Below is the piece code:

//Sample 05: Set the Path to Spy using Folder Browser Dialog
private void btnPickFolder_Click(object sender, EventArgs e)
{
    if (FolderB.ShowDialog() == DialogResult.OK)
    {
        txtFolderPath.Text = FolderB.SelectedPath;
        fileMon.Path = txtFolderPath.Text;
    }
}

5) The FileSystemWatcher component will actually start raising the events (Fig.3) when its "EnableRaisingEvents Property" is set to true. Once it starts raising the events, we will get the spied events in the corresponding handler functions. So we set this property when Start Monitor button is clicked. Below is piece of code:

//Sample 06: Enable capturing file system events
private void btnMonitor_Click(object sender, EventArgs e)
{
    fileMon.Path = txtFolderPath.Text;
    fileMon.EnableRaisingEvents = true;
}

6) The recursive checkbox will set the IncludeSubdirectories property of the component. We will get an application exception when we set this property to true when the Path property does not contain any valid path to monitor. So below is the piece of code which safeguards this situation:

//Sample 07: Enable capturing file system events
private void txtFolderPath_TextChanged(object sender, EventArgs e)
{
    if (string.IsNullOrEmpty(txtFolderPath.Text))
        chkRecursive.Enabled = false;
    else
        chkRecursive.Enabled = true;
}

7) Next, all the four events shown in Fig.3 are handled. In each handler, we will get the file name from the FileSystemEventArgs, which is passed to the handler as a parameter. As we already inside the handler we know the corresponding action say whether it is a file deletion or Rename etc. On each handler, we will check the status of the Filter checkboxes and display the information only when the corresponding check box is checked. Say for example, before displaying the file renamed action, it will check whether the filter is applied. Below is the code:

//Sample 08: Monitor all the File Events
private void fileMon_Changed(object sender, System.IO.FileSystemEventArgs e)
{
    //!under_modification: Avoids repeated consecutive ourput of Files changed per file
    if (chkModified.CheckState == CheckState.Checked && last_event_filename != e.FullPath)
    {
        content = "File Changed: " + e.FullPath + Environment.NewLine;
        txtDisplay.AppendText(content);
    }
    last_event_filename = e.FullPath;
}

private void fileMon_Created(object sender, System.IO.FileSystemEventArgs e)
{
    if (chkCreated.CheckState == CheckState.Checked)
    {
        content = "File Created: " + e.FullPath + Environment.NewLine;
        txtDisplay.AppendText(content);
    }
    last_event_filename = e.FullPath;
}

private void fileMon_Deleted(object sender, System.IO.FileSystemEventArgs e)
{
    if (chkDeleted.CheckState == CheckState.Checked)
    {
        content = "File Deleted: " + e.FullPath + Environment.NewLine;
        txtDisplay.AppendText(content);
    }
    last_event_filename = e.FullPath;
}

private void fileMon_Renamed(object sender, System.IO.RenamedEventArgs e)
{
    if (chkRenamed.CheckState == CheckState.Checked)
    {
        content = "File Renamed: New Name - "+  e.FullPath + " Old Name : " + e.OldFullPath
            + Environment.NewLine;
        txtDisplay.AppendText(content);
    }
    last_event_filename = e.FullPath;
}

5. Sample in Action

The recorded video shows spying the directory D:\Temp. First, the files are copied from C:\Temp to D:\Temp. Then a file is renamed from the D:\Temp. Then we rename a file name from Siva to Damodaran. Finally, we delete the list of files from the D:\Temp.



You can use this sample to spy your entire C:\ drive. Just Select C:\ then click on the recursive button, and the sample is now tracking entire c:\ drive. It is very useful when you are working big projects and want to know the file system that is affected by the particular workflow. 

Source Code: Download

No comments:

Post a Comment

Leave your comment(s) here.

Like this site? Tell it to your Firend :)