public override bool StartOperations() { if (base.StartOperations()) { _folderWatcher.NotifyFilter = NotificationFilter; if (MonitorChangeTypes.HasFlag(WatcherChangeTypes.Created)) { _folderWatcher.Created += ChangeReceived; } if (MonitorChangeTypes.HasFlag(WatcherChangeTypes.Renamed)) { _folderWatcher.Renamed += ChangeReceived; } if (MonitorChangeTypes.HasFlag(WatcherChangeTypes.Deleted)) { _folderWatcher.Deleted += ChangeReceived; } if (MonitorChangeTypes.HasFlag(WatcherChangeTypes.Changed)) { _folderWatcher.Changed += ChangeReceived; } _folderWatcher.EnableRaisingEvents = true; return(true); } return(false); }
public FileWatcherRx(string path, string filter, NotifyFilters notifyFilters = NotifyFilters.LastWrite, WatcherChangeTypes changeTypes = WatcherChangeTypes.Changed) { Watcher = new FileSystemWatcher { Path = path, IncludeSubdirectories = false, NotifyFilter = notifyFilters, Filter = filter, EnableRaisingEvents = true }; if (changeTypes.HasFlag(WatcherChangeTypes.Changed)) { Changed = Observable.FromEventPattern <FileSystemEventArgs>(Watcher, "Changed"); } if (changeTypes.HasFlag(WatcherChangeTypes.Created)) { Created = Observable.FromEventPattern <FileSystemEventArgs>(Watcher, "Created"); } if (changeTypes.HasFlag(WatcherChangeTypes.Deleted)) { Deleted = Observable.FromEventPattern <FileSystemEventArgs>(Watcher, "Deleted"); } if (changeTypes.HasFlag(WatcherChangeTypes.Renamed)) { Renamed = Observable.FromEventPattern <RenamedEventArgs>(Watcher, "Renamed"); } Error = Observable.FromEventPattern <ErrorEventArgs>(Watcher, nameof(Watcher.Error)); }
public FileMonitor(string path, string filter = null, WatcherChangeTypes watchedChangeTypes = WatcherChangeTypes.All) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } _fileChangedSubject = Subject.Synchronize(new SubjectSlim <FileSystemEventArgs>()); _fsw = new FileSystemWatcher(path, filter); // by default, try to reduce to a minimum the information returned by the FileSystemWatcher // to reduce the occurence of an InternalBufferOverflowException when dealing with many files _fsw.NotifyFilter = NotifyFilters.FileName; // Changed event requires NotifyFilters.LastWrite if (watchedChangeTypes.HasFlag(WatcherChangeTypes.Changed)) { _fsw.NotifyFilter |= NotifyFilters.LastWrite; } // increase internal buffer size of the FSW to avoid an InternalBufferOverflowException // (the size must be a multiple of 4096 for a better performance on Intel platform) // see http://stackoverflow.com/questions/13916595/is-it-really-that-expensive-to-increase-filesystemwatcher-internalbuffersize _fsw.InternalBufferSize = 16 * 4096; // 64KB if (watchedChangeTypes.HasFlag(WatcherChangeTypes.Changed)) { _fsw.Changed += (s, e) => _fileChangedSubject.OnNext(e); } if (watchedChangeTypes.HasFlag(WatcherChangeTypes.Created)) { _fsw.Created += (s, e) => _fileChangedSubject.OnNext(e); } if (watchedChangeTypes.HasFlag(WatcherChangeTypes.Deleted)) { _fsw.Deleted += (s, e) => _fileChangedSubject.OnNext(e); } if (watchedChangeTypes.HasFlag(WatcherChangeTypes.Renamed)) { _fsw.Renamed += (s, e) => _fileChangedSubject.OnNext(e); } _fsw.Error += (s, e) => _fileChangedSubject.OnError(e.GetException()); }
private void AddEventSubscriptions(FileSystemWatcher fileWatcher, WatcherChangeTypes changeTypes) { if (changeTypes.HasFlag(WatcherChangeTypes.Changed)) { fileWatcher.Changed += OnFileChanged; } if (changeTypes.HasFlag(WatcherChangeTypes.Created)) { fileWatcher.Created += OnFileChanged; } if (changeTypes.HasFlag(WatcherChangeTypes.Deleted)) { fileWatcher.Deleted += OnFileChanged; } if (changeTypes.HasFlag(WatcherChangeTypes.Renamed)) { fileWatcher.Renamed += OnFileChanged; } }
private void AddEventSubscriptions(FileSystemWatcher fileWatcher, WatcherChangeTypes changeTypes) { if (changeTypes.HasFlag(WatcherChangeTypes.Changed)) { fileWatcher.Changed += OnFileChanged; } if (changeTypes.HasFlag(WatcherChangeTypes.Created)) { fileWatcher.Created += OnFileChanged; } if (changeTypes.HasFlag(WatcherChangeTypes.Deleted)) { fileWatcher.Deleted += OnFileChanged; } if (changeTypes.HasFlag(WatcherChangeTypes.Renamed)) { fileWatcher.Renamed += OnFileChanged; } }
private void DetachHandlersForChangeTypes(WatcherChangeTypes changeType) { if (changeType.HasFlag(WatcherChangeTypes.Created)) { Created -= WaitForChangeHandler; } if (changeType.HasFlag(WatcherChangeTypes.Deleted)) { Deleted -= WaitForChangeHandler; } if (changeType.HasFlag(WatcherChangeTypes.Changed)) { Changed -= WaitForChangeHandler; } if (changeType.HasFlag(WatcherChangeTypes.Renamed)) { Renamed -= WaitForChangeRenameHandler; } }
private static IObservable <EventPattern <FileSystemEventArgs> > CreateObservableEventsWithoutRenamed( FileSystemWatcher watcher, WatcherChangeTypes changes) { Contract.Requires(watcher != null); IObservable <EventPattern <FileSystemEventArgs> > events = null; if (changes.HasFlag(WatcherChangeTypes.Changed)) { events = Observable.FromEventPattern <FileSystemEventHandler, FileSystemEventArgs>( eh => eh.Invoke, eh => watcher.Changed += eh, eh => watcher.Changed -= eh); } if (changes.HasFlag(WatcherChangeTypes.Created)) { var created = Observable.FromEventPattern <FileSystemEventHandler, FileSystemEventArgs>( eh => eh.Invoke, eh => watcher.Created += eh, eh => watcher.Created -= eh); events = events == null ? created : events.Merge(created); } if (changes.HasFlag(WatcherChangeTypes.Deleted)) { var deleted = Observable.FromEventPattern <FileSystemEventHandler, FileSystemEventArgs>( eh => eh.Invoke, eh => watcher.Deleted += eh, eh => watcher.Deleted -= eh); events = events == null ? deleted : events.Merge(deleted); } return(events); }
/// <summary> /// Starts watching the file system. /// </summary> /// <param name="cancellationToken"> /// A cancellation token that should be used to cancel the watching task. /// </param> /// <returns>A <see cref="Task"/> that represent the watching process.</returns> public async Task Watch(CancellationToken cancellationToken) { try { var watcher = new FileSystemWatcher(_dir) { IncludeSubdirectories = true }; cancellationToken.Register(() => watcher?.Dispose()); if (_events.HasFlag(WatcherChangeTypes.Created)) { watcher.Created += OnWatcherFileSystemEvent; } if (_events.HasFlag(WatcherChangeTypes.Changed)) { watcher.Changed += OnWatcherFileSystemEvent; } if (_events.HasFlag(WatcherChangeTypes.Deleted)) { watcher.Deleted += OnWatcherFileSystemEvent; } if (_events.HasFlag(WatcherChangeTypes.Renamed)) { watcher.Renamed += OnWatcherRenameEvent; } watcher.EnableRaisingEvents = true; await Task.Delay(Timeout.Infinite, cancellationToken); } catch (TaskCanceledException) { Console.WriteLine("Stopping by request..."); } }
private static IObservable <FileSystemNotification> CreateObservableEvents( FileSystemWatcher watcher, WatcherChangeTypes changes) { Contract.Requires(watcher != null); Contract.Ensures(Contract.Result <IObservable <FileSystemNotification> >() != null); IObservable <FileSystemNotification> allEvents = null; var events = CreateObservableEventsWithoutRenamed(watcher, changes); if (events != null) { allEvents = from e in events select new FileSystemNotification( e.EventArgs.ChangeType, e.EventArgs.Name, e.EventArgs.FullPath); } if (changes.HasFlag(WatcherChangeTypes.Renamed)) { var renamed = Observable .FromEventPattern <RenamedEventHandler, RenamedEventArgs>( eh => eh.Invoke, eh => watcher.Renamed += eh, eh => watcher.Renamed -= eh) .Select(e => new FileSystemNotification( e.EventArgs.OldName, e.EventArgs.OldFullPath, e.EventArgs.Name, e.EventArgs.FullPath)); allEvents = allEvents == null ? renamed : allEvents.Merge(renamed); } if (allEvents == null) { throw new InvalidEnumArgumentException("changes", (int)changes, typeof(WatcherChangeTypes)); } return(allEvents); }
public WaitForChangedResult WaitForChanged(WatcherChangeTypes type, int timeout) { if (type == WatcherChangeTypes.Renamed || type == WatcherChangeTypes.Changed || type == (WatcherChangeTypes.Changed | WatcherChangeTypes.Renamed)) // Polling cannot monitor these changes { throw new NotImplementedException("File System Poller can not monitor \"Rename\" or \"Changed\" item changes."); } // Using this stopwatch to check I'm staying in the method longer then the timeout set Stopwatch timeInMethodStopwatch = Stopwatch.StartNew(); Interlocked.Increment(ref _waiters); while (true) { int remainingTimeToWait = timeout - (int)timeInMethodStopwatch.ElapsedMilliseconds; var timedOut = !_changesWatchingEvent.WaitOne(remainingTimeToWait); if (timedOut) // wait timed out, exit method. { Interlocked.Decrement(ref _waiters); return(new WaitForChangedResult() { ChangeType = type, TimedOut = true }); } // wait didn't time out - check results WaitForChangedResult results; lock (_latestChangeLocker) { results = _latestChange; } // Check if the reported results match the requestsed result type. // Otherwise - continue waiting for more changes if (type.HasFlag(results.ChangeType)) { Interlocked.Decrement(ref _waiters); return(results); } } }
private async void OnLibraryChanged(WatcherChangeTypes changeType, string oldPath, string newPath) { if (newPath != null && (!newPath.ToLowerInvariant().EndsWith(ShellLibraryItem.EXTENSION, StringComparison.Ordinal) || !File.Exists(newPath))) { System.Diagnostics.Debug.WriteLine($"Ignored library event: {changeType}, {oldPath} -> {newPath}"); return; } System.Diagnostics.Debug.WriteLine($"Library event: {changeType}, {oldPath} -> {newPath}"); if (connection?.IsConnected ?? false) { var response = new ValueSet { { "Library", newPath ?? oldPath } }; switch (changeType) { case WatcherChangeTypes.Deleted: case WatcherChangeTypes.Renamed: response["OldPath"] = oldPath; break; default: break; } if (!changeType.HasFlag(WatcherChangeTypes.Deleted)) { var library = SafetyExtensions.IgnoreExceptions(() => new ShellLibrary2(Shell32.ShellUtil.GetShellItemForPath(newPath), true)); if (library == null) { Program.Logger.Warn($"Failed to open library after {changeType}: {newPath}"); return; } response["Item"] = JsonConvert.SerializeObject(ShellFolderExtensions.GetShellLibraryItem(library, newPath)); library.Dispose(); } // Send message to UWP app to refresh items await Win32API.SendMessageAsync(connection, response); } }
public WaitForChangedResult WaitForChanged(WatcherChangeTypes type) { if (type == WatcherChangeTypes.Renamed || type == WatcherChangeTypes.Changed || type == (WatcherChangeTypes.Changed | WatcherChangeTypes.Renamed)) // Polling cannot monitor these changes { throw new NotImplementedException("File System Poller can not monitor \"Rename\" or \"Changed\" file changes."); } while (true) { Interlocked.Increment(ref _waiters); _changesWatchingEvent.WaitOne(); Interlocked.Decrement(ref _waiters); WaitForChangedResult results; lock (_latestChangeLocker) { results = _latestChange; } // Check if the report fits the one the current thread is looking for if (type.HasFlag(results.ChangeType)) { // It does, returning the report. return(results); } else { // It doesn't. // allowing a signle other thread to examine it this report: _changesWatchingEvent.Set(); // making sure the event is reset when the current thread returns to it. (If a thread is waiting it will exit after the .Set and before the .Reset) _changesWatchingEvent.Reset(); } } }
public static IDisposable OnAnyEvent(this FileSystemWatcher source, WatcherChangeTypes changeTypes, FileSystemEventHandler handler, int delay) { var cancellations = new Dictionary <string, CancellationTokenSource>( StringComparer.OrdinalIgnoreCase); var locker = new object(); if (changeTypes.HasFlag(WatcherChangeTypes.Created)) { source.Created += FileSystemWatcher_Event; } if (changeTypes.HasFlag(WatcherChangeTypes.Deleted)) { source.Deleted += FileSystemWatcher_Event; } if (changeTypes.HasFlag(WatcherChangeTypes.Changed)) { source.Changed += FileSystemWatcher_Event; } if (changeTypes.HasFlag(WatcherChangeTypes.Renamed)) { source.Renamed += FileSystemWatcher_Event; } return(new Disposable(() => { source.Created -= FileSystemWatcher_Event; source.Deleted -= FileSystemWatcher_Event; source.Changed -= FileSystemWatcher_Event; source.Renamed -= FileSystemWatcher_Event; })); async void FileSystemWatcher_Event(object sender, FileSystemEventArgs e) { var key = e.FullPath; var cts = new CancellationTokenSource(); lock (locker) { if (cancellations.TryGetValue(key, out var existing)) { existing.Cancel(); } cancellations[key] = cts; } try { await Task.Delay(delay, cts.Token); // Omitting ConfigureAwait(false) is intentional here. // Continuing in the captured context is desirable. } catch (TaskCanceledException) { return; } lock (locker) { if (cancellations.TryGetValue(key, out var existing) && existing == cts) { cancellations.Remove(key); } } cts.Dispose(); handler(sender, e); } }
public WaitForChangedResult WaitForChanged(WatcherChangeTypes type, int timeout) { if (type == WatcherChangeTypes.Renamed || type == WatcherChangeTypes.Changed || type == (WatcherChangeTypes.Changed | WatcherChangeTypes.Renamed)) // Polling cannot monitor these changes { throw new NotImplementedException("File System Poller can not monitor \"Rename\" or \"Changed\" item changes."); } // Using this stopwatch to check I'm staying in the method longer then the timeout set Stopwatch timeInMethodStopwatch = Stopwatch.StartNew(); Interlocked.Increment(ref _waiters); while (true) { int remainingTimeToWait = timeout - (int)timeInMethodStopwatch.ElapsedMilliseconds; var timedOut = !_changesWatchingEvent.WaitOne(remainingTimeToWait); if (timedOut) // wait timed out, exit method. { Interlocked.Decrement(ref _waiters); return new WaitForChangedResult() { ChangeType = type, TimedOut = true }; } // wait didn't time out - check results WaitForChangedResult results; lock (_latestChangeLocker) { results = _latestChange; } // Check if the reported results match the requestsed result type. // Otherwise - continue waiting for more changes if (type.HasFlag(results.ChangeType)) { Interlocked.Decrement(ref _waiters); return results; } } }
public WaitForChangedResult WaitForChanged(WatcherChangeTypes type) { if (type == WatcherChangeTypes.Renamed || type == WatcherChangeTypes.Changed || type == (WatcherChangeTypes.Changed | WatcherChangeTypes.Renamed)) // Polling cannot monitor these changes { throw new NotImplementedException("File System Poller can not monitor \"Rename\" or \"Changed\" file changes."); } while (true) { Interlocked.Increment(ref _waiters); _changesWatchingEvent.WaitOne(); Interlocked.Decrement(ref _waiters); WaitForChangedResult results; lock (_latestChangeLocker) { results = _latestChange; } // Check if the report fits the one the current thread is looking for if (type.HasFlag(results.ChangeType)) { // It does, returning the report. return results; } else { // It doesn't. // allowing a signle other thread to examine it this report: _changesWatchingEvent.Set(); // making sure the event is reset when the current thread returns to it. (If a thread is waiting it will exit after the .Set and before the .Reset) _changesWatchingEvent.Reset(); } } }