示例#1
0
        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);
        }
示例#2
0
 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));
 }
示例#3
0
        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());
        }
示例#4
0
        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;
            }
        }
示例#6
0
        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);
        }
示例#8
0
        /// <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);
                }
            }
        }
示例#11
0
        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();
                }
            }
        }