web analytics

How to Use FileSystemWatcher to Monitor File Change and Creation in C#?

Options

codeling 1599 - 6654
@2016-01-01 11:24:08

The FileSystemWatcher class d in the System.IO namespace provides all of the functionality required to monitor a directory on a disk and identify when its contents change. It achieves this by linking directly to the file system notifications provided by the Windows operating system and raising events when items change. It provides four events that are raised to indicate a change to a file or folder:

  • Changed. Raised when a file or a folder is modified.
  • Created. Raised when a new file or folder is created.
  • Deleted. Raised when an existing file or folder is deleted.
  • Renamed. Raised when an existing file or folder is renamed.

You can configure FileSystemWatcher to watch for changes in files and subdirectories of the specified directory by setting Filter and NotifyFilter property, such as

  • To watch for changes in all files, set the Filter property to an empty string ("") or use wildcards ("*.*").
  • To watch a specific file, set the Filter property to the file name. For example, to watch for changes in the file MyDoc.txt, set the Filter property to "MyDoc.txt".
  • To watch for changes in a certain type of file. For example, to watch for changes in xml files, set the Filter property to "*.xml".
  • To watch for changes in Attributes, the LastWrite date and time, or the Size of files or directories. This is done by setting the NotifyFilter property to one of the NotifyFilters values.

The following example creates a FileSystemWatcher to watch the directory specified at run time. The component is set to watch for changes in LastWrite and LastAccess time, the creation, deletion, or renaming of text files in the directory. If a file is changed, created, or deleted, the path to the file prints to the console. When a file is renamed, the old and new paths print to the console.

using System;
using System.IO;
using System.Security.Permissions;

public class Watcher
{
    public static void Main()
    {
       Run();

    }
    [PermissionSet(SecurityAction.Demand, Name="FullTrust")]
    public static void Run()
    {
        string[] args = System.Environment.GetCommandLineArgs();

        // If a directory is not specified, exit program.
        if(args.Length != 2)
        {
            // Display the proper way to call the program.
            Console.WriteLine("Usage: Watcher.exe (directory)");
            return;
        }
        // Create a new FileSystemWatcher and set its properties.
        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Path = args[1];

        /* Watch for changes in LastAccess and LastWrite times, and
           the renaming of files or directories. */
        watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
           | NotifyFilters.FileName | NotifyFilters.DirectoryName;
 
       // Only watch text files.
        watcher.Filter = "*.txt";

        // Add event handlers.
        watcher.Changed += new FileSystemEventHandler(OnChanged);
        watcher.Created += new FileSystemEventHandler(OnChanged);
        watcher.Deleted += new FileSystemEventHandler(OnChanged);
        watcher.Renamed += new RenamedEventHandler(OnRenamed);
        // Begin watching.
        watcher.EnableRaisingEvents = true;

        // Wait for the user to quit the program.
        Console.WriteLine("Press \'q\' to quit the sample.");
        while(Console.Read()!='q');
    }
    // Define the event handlers.
    private static void OnChanged(object source, FileSystemEventArgs e)
    {
        // Specify what is done when a file is changed, created, or deleted.
       Console.WriteLine("File: " +  e.FullPath + " " + e.ChangeType);
    }

    private static void OnRenamed(object source, RenamedEventArgs e)
    {
        // Specify what is done when a file is renamed.
        Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
    }
}
@2016-01-01 11:28:35

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. When the Changed, Created, Deleted, and Renamed events are handled by a visual Windows Forms component, such as a Button, accessing the component through the system thread pool might not work, or may result in a cross-threading operation and an IllegalOperationException being thrown. Avoid this by setting SynchronizingObject to a Windows Forms component, which causes the methods that handle the Changed, Created, Deleted, and Renamed events to be called on the same thread on which the component was created.

FileSystemWatcher watcher;
 
public FileMonitorForm()
{
    InitializeComponent();

    _watcher = new FileSystemWatcher();
    _watcher.SynchronizingObject = this;
}
@2016-01-01 12:02:19

Monitoring Subfolders

The IncludeSubdirectories property can be used to indicate whether subfolders of the monitored directory should be monitored. When set to true, the entire hierarchy of folders beneath the specified path is observed and any changes cause events to be raised.

This option should be used with care as it can lead to unexpectedly large numbers of notifications being added to the buffer, increasing the risk that it will be overfilled.

@2016-01-01 12:18:50

Buffer Size and the Error Event

The FileSystemWatcher class works by capturing all of the relevant file and older changes and placing them into a buffer. This is then processed one change at a time until all of the notifications have been dealt with and the buffer is empty. By default, the internal buffer has a size of eight kilobytes (8192 bytes). Each event can take up to sixteen bytes of the buffer for its data, not including the file name. This means that when there are a lot of changes in a short period of time, the buffer can quickly become overloaded and notifications can be lost.

One way to manage the buffer size problem is to change the maximum size that is permitted. If you know that your program is likely to process large numbers of file changes in a short period, you can change the value in the InternalBufferSize property. This property allows the size of the buffer to be specified as a number of bytes. Care should be taken as the buffer is held in memory that cannot be swapped to disk so this memory becomes unavailable to other programs. The size selected should be a multiple of 4096 to give the best performance.

_watcher.InternalBufferSize = 4096 * 50;

Each time the buffer size limit is reached, the FileSystemWatcher object raises an Error event. This event allows you to identify that there has been a change but the details of the file or folder modified will not be available. Generally you would log this or create some kind of notification so that a recovery can be attempted.

To capture the Error event in the sample program, add the following line to the end of the form's constructor:

_watcher.Error += new ErrorEventHandler(LogBufferError);

To process this event, add the following method to the form's class:

void LogBufferError(object sender, ErrorEventArgs e)
{
    //FileWatcher buffer limit exceeded
}

Comments

You must Sign In to comment on this topic.


© 2024 Digcode.com