C# - monitor directory activity using FileSystemWatcher class

Posted on 22 473 views

System.IO.FileSystemWatcher class allows you to monitor physical directory activity, listen to the file system change notifications and raises events when a directory, or file in a directory changes. (For complete MSDN documentation please visit: http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx).

Screenshot of demo application

I'we made small WPF application that will demonstrate you how to use this class.
As you can see, it's pretty simple. In TextBox you specify which folder you want to monitor. ListBox is here to show activity in a readable way.



XAML code of UI

Definition of UI is following:

        <Window x:Class="MB.FileSystemWatcher.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="428" Width="714" Loaded="Window_Loaded" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
    <Grid>
        <TextBox Height="23" HorizontalAlignment="Left" Name="TextBoxFolderPath" 
        VerticalAlignment="Top" Width="549" Margin="12,12,0,0" IsReadOnly="True" Text=""></TextBox>

        <Button Content="Browse folder" Height="23" HorizontalAlignment="Right" Margin="0,11,12,0" Name="ButtonOpenFolderDialog" 
        VerticalAlignment="Top" Width="113" Click="ButtonOpenFolderDialog_Click"></Button>

        <ListBox Height="328" HorizontalAlignment="Left" Margin="12,49,0,0" Name="ListBoxFileSystemWatcher" 
        VerticalAlignment="Top" Width="668"></ListBox>

    </Grid>
</Window>
    

Complete source code

Because of the simplicity of the example, I write down the complete code in one section with all comments.
It's pretty basic thing: instantiate FileSystemWatcher class, set handlers, start monitoring, and display the action message.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MB.FileSystemWatcher
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Replace this with path of the directory you want to watch
            this.TextBoxFolderPath.Text = @"F:\------ PRO 1 - MATIJABOZICEVIC.COM\BLOG\MB.FileSystemWatcher\SampleDirectory";

            // Start file system watcher on selected folder
            StartFileSystemWatcher();
        }

        private void ButtonOpenFolderDialog_Click(object sender, RoutedEventArgs e)
        {
            // Browse folder to monitor
            System.Windows.Forms.FolderBrowserDialog folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();

            if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.TextBoxFolderPath.Text = folderBrowserDialog.SelectedPath;
            }

            // Start file system watcher on selected folder
            StartFileSystemWatcher();
        }

        private void StartFileSystemWatcher()
        {
            string folderPath = this.TextBoxFolderPath.Text;

            // If there is no folder selected, to nothing
            if (string.IsNullOrWhiteSpace(folderPath))
                return;

            System.IO.FileSystemWatcher fileSystemWatcher = new System.IO.FileSystemWatcher();

            // Set folder path to watch
            fileSystemWatcher.Path = folderPath;

            // Gets or sets the type of changes to watch for.
            // In this case we will watch change of filename, last modified time, size and directory name
            fileSystemWatcher.NotifyFilter = System.IO.NotifyFilters.FileName |
                System.IO.NotifyFilters.LastWrite |
                System.IO.NotifyFilters.Size |
                System.IO.NotifyFilters.DirectoryName;


            // Event handlers that are watching for specific event
            fileSystemWatcher.Created += new System.IO.FileSystemEventHandler(fileSystemWatcher_Created);
            fileSystemWatcher.Changed += new System.IO.FileSystemEventHandler(fileSystemWatcher_Changed);
            fileSystemWatcher.Deleted += new System.IO.FileSystemEventHandler(fileSystemWatcher_Deleted);
            fileSystemWatcher.Renamed += new System.IO.RenamedEventHandler(fileSystemWatcher_Renamed);

            // NOTE: If you want to monitor specified files in folder, you can use this filter
            // fileSystemWatcher.Filter

            // START watching
            fileSystemWatcher.EnableRaisingEvents = true;
        }

        // ----------------------------------------------------------------------------------
        // Events that do all the monitoring
        // ----------------------------------------------------------------------------------

        void fileSystemWatcher_Created(object sender, System.IO.FileSystemEventArgs e)
        {
            DisplayFileSystemWatcherInfo(e.ChangeType, e.Name);
        }

        void fileSystemWatcher_Changed(object sender, System.IO.FileSystemEventArgs e)
        {
            DisplayFileSystemWatcherInfo(e.ChangeType, e.Name);
        }

        void fileSystemWatcher_Deleted(object sender, System.IO.FileSystemEventArgs e)
        {
            DisplayFileSystemWatcherInfo(e.ChangeType, e.Name);
        }

        void fileSystemWatcher_Renamed(object sender, System.IO.RenamedEventArgs e)
        {
            DisplayFileSystemWatcherInfo(e.ChangeType, e.Name, e.OldName);
        }

        // ----------------------------------------------------------------------------------

        void DisplayFileSystemWatcherInfo(System.IO.WatcherChangeTypes watcherChangeTypes, string name, string oldName = null)
        {
            if (watcherChangeTypes == System.IO.WatcherChangeTypes.Renamed)
            {
                // When using FileSystemWatcher event's be aware that these events will be called on a separate thread automatically!!!
                // If you call method AddListLine() in a normal way, it will throw following exception: 
                // "The calling thread cannot access this object because a different thread owns it"
                // To fix this, you must call this method using Dispatcher.BeginInvoke(...)!
                Dispatcher.BeginInvoke(new Action(() => { AddListLine(string.Format("{0} -> {1} to {2} - {3}", watcherChangeTypes.ToString(), oldName, name, DateTime.Now)); }));
            }
            else
            {
                Dispatcher.BeginInvoke(new Action(() => { AddListLine(string.Format("{0} -> {1} - {2}", watcherChangeTypes.ToString(), name, DateTime.Now)); }));
            }
        }

        public void AddListLine(string text)
        {
            this.ListBoxFileSystemWatcher.Items.Add(text);
        }
    }
}
    

NOTE: as I mentioned, if you want to monitor specified files in folder, you can use Filter property of FileSystemWatcher class. If you want to play with this filter, you can also visit following link for more information: http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.filter(v=vs.110).aspx.