FFMG / myoddweb.directorywatcher

A fast and reliable, (non blocking!), .NET/C++ File/Directory watcher, complete rewrite of FileSystemWatcher to ensure speed/accuracy/reliability/suppress duplicate events.
MIT License
50 stars 12 forks source link
directory-watcher directorywatcher filesystemwatcher notifications watcher

Myoddweb.Directorywatcher Release

A fast and reliable File/Directory watcher for c#/c++ to replace the current .NET FileSystemWatcher class.

What it does

What it doesn't do

Installing

Nuget

NuGet Status NuGet Count

Package manager

Install-Package MyOddWeb.DirectoryWatcher

CLI

.NET

dotnet add package MyOddWeb.DirectoryWatcher

Packet

paket add MyOddWeb.DirectoryWatcher

Use case

My needs were to, reliably, monitor entire volumes for created/deleted/renamed files. I do really care for pattern matching.

The issue(s) with FileSystemWatcher

The current version of File Watcher is great, but it does have a couple of issues.

Examples

Simple Watch

Add all the directories we want to 'observe'

    using( var watch = new Watcher() )
    {
      watch.Add(new Request("c:\\", true));
      watch.Add(new Request("d:\\foo\\bar\\", true));
      watch.Add(new Request("y:\\", true));

      // do something amazing with the data
      watch.OnAddedAsync += async (f, t) =>
      {
        // ..
      };

      // start watching
      watch.Start();

      // add some more
       watch.Add(new Request("z:\\", false));

      // optional stop in this case
      watch.Stop();
    }

You can start watching at any point

    // create Watcher
    var watcher = new Watcher();

    // Add a request.
    watch.Add(new Request("y:\\", true));

    // start watching
    watch.Start();

    // add some more
    watch.Add(new Request("z:\\", false));

Get notifications in case a file is created.

    watch.OnAddedAsync += async (f, t) =>
    {
      Console.ForegroundColor = ConsoleColor.Green;
      Console.WriteLine(
        $"[{f.DateTimeUtc.Hour}:{f.DateTimeUtc.Minute}:{f.DateTimeUtc.Second}]:{f.FileSystemInfo}");
      Console.ForegroundColor = foreground;
    };

we get given the file that was added as well as a cancellation token

And when we are done stop it ...

    watch.Stop();

Or Dispose of it

    watch.Dispose();

Your own 'Watcher' interface

You can create your own watcher interface

public class Watcher : IWatcher3
{
  // Implement IWatcher3
}

Watched Events

When a file event is raised we send a IFileSystemEvent event.

    /// <summary>
    /// The file system event.
    /// </summary>
    FileSystemInfo FileSystemInfo { get; }

    /// <summary>
    ///  Gets the full path of the directory or file.
    /// </summary>
    /// <returns>A string containing the full path.</returns>
    string FullName { get; }

    /// <summary>
    ///     For files, gets the name of the file. For directories, gets the name of the last
    ///     directory in the hierarchy if a hierarchy exists. Otherwise, the Name property
    ///     gets the name of the directory.
    /// </summary>
    /// <returns>A string that is the name of the parent directory, the name of the last directory
    ///     in the hierarchy, or the name of a file, including the file name extension.
    /// </returns>
    string Name { get; }

    /// <summary>
    /// The Action
    ///  Added
    ///  Removed
    ///  Touched
    ///  Renamed
    /// </summary>
    EventAction Action { get; }

    /// <summary>
    /// An error code related to the event, (if any)
    /// </summary>
    EventError Error { get; }

    /// <summary>
    /// The UTC date time of the event.
    /// </summary>
    DateTime DateTimeUtc { get; }

    /// <summary>
    /// Boolean if the update is a file or a directory.
    /// </summary>
    bool IsFile { get; }

    /// <summary>
    /// Return if the event is a certain action
    /// (same as Action == action)
    /// </summary>
    /// <param name="action"></param>
    /// <returns></returns>
    bool Is(EventAction action );

Statistics

You can get statistics at various intervals for the events being watched.

All you need to do is add Rates to your watchers

    using( var watch = new Watcher() )
    {
      // watch the folder with stats every 10000 ms
      // a value of 0, (default), turns it off.
      watch.Add(new Request("c:\\", true, new Rates(10000, 50 )));

      // do something amazing with the statistics
      // the values is `IStatistics` with a cancellation token
      watch.OnStatisticsAsync += async (s, t) =>
      {
        // ..
      };

      // start watching
      watch.Start();

      // ... do some clever stuff.

      // optional stop in this case
      watch.Stop();
    }

Logger

You can watch for certain events

    using( var watch = new Watcher() )
    {
      // watch the folder with stats every 10000 ms
      // a value of 0, (default), turns it off.
      watch.Add(new Request("c:\\", true ));

      // do something amazing with the message
      // the values is `ILoggerEvent` with a cancellation token
      watch.OnLoggerAsync += async (e, t) =>
      {
        // ..
      };

      // start watching
      watch.Start();

      // ... do some clever stuff.

      // optional stop in this case
      watch.Stop();
    }