Skip to content

Instantly share code, notes, and snippets.

@rkttu
Last active June 6, 2023 09:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rkttu/1e1458acf72b553063e031770bca51f3 to your computer and use it in GitHub Desktop.
Save rkttu/1e1458acf72b553063e031770bca51f3 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Threading.Tasks;
// Compatible with .NET Framework 4 Client Profile & legacy C# compiler.
namespace ClouDeveloper
{
public static class FileSystemWatch
{
public const string DefaultFilter =
"*.*";
public const WatcherChangeTypes DefaultWatcherChangeType =
WatcherChangeTypes.All;
public const NotifyFilters DefaultNotifyFilter =
NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
public const TaskCreationOptions DefaultTaskCreationOption =
TaskCreationOptions.None;
public const int DefaultInternalBufferSize =
8192;
public static Task<FileSystemEventArgs> WatchEventAsync(this DriveInfo driveInfo,
string filter = DefaultFilter,
bool includeSubdirectories = false,
bool expandEnvironmentVariable = true,
WatcherChangeTypes @event = DefaultWatcherChangeType,
NotifyFilters notifyFilter = DefaultNotifyFilter,
int internalBufferSize = DefaultInternalBufferSize,
TaskCreationOptions option = DefaultTaskCreationOption)
{
if (driveInfo == null)
throw new ArgumentNullException("driveInfo");
return WatchFileSystemEventAsync(driveInfo.RootDirectory.FullName,
filter: filter,
includeSubdirectories: includeSubdirectories,
expandEnvironmentVariable: expandEnvironmentVariable,
@event: @event,
notifyFilter: notifyFilter,
internalBufferSize: internalBufferSize,
option: option);
}
public static Task<FileSystemEventArgs> WatchEventAsync(this FileInfo fileInfo,
bool expandEnvironmentVariable = true,
WatcherChangeTypes @event = DefaultWatcherChangeType,
NotifyFilters notifyFilter = DefaultNotifyFilter,
int internalBufferSize = DefaultInternalBufferSize,
TaskCreationOptions option = DefaultTaskCreationOption)
{
if (fileInfo == null)
throw new ArgumentNullException("fileInfo");
return WatchFileSystemEventAsync(fileInfo.DirectoryName,
filter: fileInfo.Name,
includeSubdirectories: false,
expandEnvironmentVariable: expandEnvironmentVariable,
@event: @event,
notifyFilter: notifyFilter,
internalBufferSize: internalBufferSize,
option: option);
}
public static Task<FileSystemEventArgs> WatchEventAsync(this DirectoryInfo directoryInfo,
string filter = DefaultFilter,
bool includeSubdirectories = false,
bool expandEnvironmentVariable = true,
WatcherChangeTypes @event = DefaultWatcherChangeType,
NotifyFilters notifyFilter = DefaultNotifyFilter,
int internalBufferSize = DefaultInternalBufferSize,
TaskCreationOptions option = DefaultTaskCreationOption)
{
if (directoryInfo == null)
throw new ArgumentNullException("directoryInfo");
return WatchFileSystemEventAsync(directoryInfo.FullName,
filter: filter,
includeSubdirectories: includeSubdirectories,
expandEnvironmentVariable: expandEnvironmentVariable,
@event: @event,
notifyFilter: notifyFilter,
internalBufferSize: internalBufferSize,
option: option);
}
public static Task<FileSystemEventArgs> WatchFileSystemEventAsync(string directoryPath,
string filter = DefaultFilter,
bool includeSubdirectories = false,
bool expandEnvironmentVariable = true,
WatcherChangeTypes @event = DefaultWatcherChangeType,
NotifyFilters notifyFilter = DefaultNotifyFilter,
int internalBufferSize = DefaultInternalBufferSize,
TaskCreationOptions option = DefaultTaskCreationOption)
{
if (String.IsNullOrWhiteSpace(directoryPath))
throw new ArgumentNullException("directoryPath");
if (@event == default(WatcherChangeTypes))
throw new ArgumentException("At least one or more watcher change type shoud be selected.", "event");
if (notifyFilter == default(NotifyFilters))
throw new ArgumentException("At least one or more notify filter shoud be selected.", "notifyFilter");
var result = new TaskCompletionSource<FileSystemEventArgs>(option);
var watcher = new FileSystemWatcher(
expandEnvironmentVariable ? Environment.ExpandEnvironmentVariables(directoryPath) : directoryPath,
expandEnvironmentVariable ? Environment.ExpandEnvironmentVariables(filter) : filter)
{
EnableRaisingEvents = true,
IncludeSubdirectories = includeSubdirectories,
NotifyFilter = notifyFilter,
InternalBufferSize = internalBufferSize
};
var disposeHandler = new EventHandler((sender, e) => result.TrySetCanceled());
var errorHandler = new ErrorEventHandler((sender, e) => result.TrySetException(e.GetException()));
var changedHandler = default(FileSystemEventHandler);
var createdHandler = default(FileSystemEventHandler);
var deletedHandler = default(FileSystemEventHandler);
var renamedHandler = default(RenamedEventHandler);
watcher.Disposed += disposeHandler;
watcher.Error += errorHandler;
if (@event.HasFlag(WatcherChangeTypes.Changed))
watcher.Changed += changedHandler = (sender, e) => result.TrySetResult(e);
if (@event.HasFlag(WatcherChangeTypes.Created))
watcher.Created += createdHandler = (sender, e) => result.TrySetResult(e);
if (@event.HasFlag(WatcherChangeTypes.Deleted))
watcher.Deleted += deletedHandler = (sender, e) => result.TrySetResult(e);
if (@event.HasFlag(WatcherChangeTypes.Renamed))
watcher.Renamed += renamedHandler = (sender, e) => result.TrySetResult(e);
return result.Task.ContinueWith(args =>
{
if (watcher != null)
{
watcher.Disposed -= disposeHandler;
watcher.Error -= errorHandler;
if (changedHandler != null) watcher.Changed -= changedHandler;
if (createdHandler != null) watcher.Created -= createdHandler;
if (deletedHandler != null) watcher.Deleted -= deletedHandler;
if (renamedHandler != null) watcher.Renamed -= renamedHandler;
watcher.Dispose();
watcher = null;
}
return args.Result;
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment