File Watcher
#region MIT License /* * Copyright (c) 2010 Nathan Palmer * http://www.nathanpalmer.com/ * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #endregion using System; using System.Collections; using System.IO; using System.Threading; namespace SimpleScheduler.Common { public class FileWatcher : IDisposable { private readonly Hashtable fileChangeTable = new Hashtable(); private readonly ReaderWriterLockSlim fileChangeTableLock = new ReaderWriterLockSlim(); private readonly FileSystemWatcher watcher = new FileSystemWatcher(); public event FileSystemEventHandler Changed; public void InvokeChanged(FileSystemEventArgs e) { FileSystemEventHandler handler = Changed; if (handler != null) handler(this, e); } public event RenamedEventHandler Renamed; public void InvokeRenamed(RenamedEventArgs e) { RenamedEventHandler handler = Renamed; if (handler != null) handler(this, e); } public event FileSystemEventHandler Deleted; public void InvokeDeleted(FileSystemEventArgs e) { FileSystemEventHandler handler = Deleted; if (handler != null) handler(this, e); } public FileWatcher(string FolderPath) { watcher.Path = FolderPath; watcher.Filter = "*.xml"; watcher.Created += new FileSystemEventHandler(OnFileSystemChanged); watcher.Changed += new FileSystemEventHandler(OnFileSystemChanged); watcher.Renamed += new RenamedEventHandler(OnFileSystemRenamed); watcher.Deleted += new FileSystemEventHandler(OnFileSystemDeleted); watcher.EnableRaisingEvents = true; } private void OnFileSystemDeleted(object sender, FileSystemEventArgs e) { InvokeDeleted(e); } private void OnFileSystemRenamed(object sender, RenamedEventArgs e) { InvokeRenamed(e); } private void OnFileSystemChanged(object sender, FileSystemEventArgs e) { fileChangeTableLock.EnterWriteLock(); try { if (!(fileChangeTable.Contains(e.FullPath))) { FileInfo fInfo = new FileInfo(e.FullPath); fileChangeTable.Add(e.FullPath, e); new Thread(() => CheckFileStatus(fInfo)).Start(); } else { Console.WriteLine(string.Format("Ignoring duplicate change request for '{0}'", e.Name)); } } finally { fileChangeTableLock.ExitWriteLock(); } } public void CheckFileStatus(FileInfo fInfo) { long fileSize = 0; while (fileSize != fInfo.Length) { Console.WriteLine(string.Format("File size of '{0}' does not match '{1}' waiting for 2.5 seconds", fileSize, fInfo.Length)); fileSize = fInfo.Length; Thread.Sleep(2500); fInfo.Refresh(); } fileChangeTableLock.EnterWriteLock(); try { if (fileChangeTable.Contains(fInfo.FullName)) { fileChangeTable.Remove(fInfo.FullName); InvokeChanged(new FileSystemEventArgs(WatcherChangeTypes.Changed, fInfo.DirectoryName, fInfo.Name)); } } finally { fileChangeTableLock.ExitWriteLock(); } } public void Dispose() { watcher.EnableRaisingEvents = false; watcher.Created -= new FileSystemEventHandler(OnFileSystemChanged); watcher.Changed -= new FileSystemEventHandler(OnFileSystemChanged); } } }
1. | Set NotifyFilter of FileSystemWatcher | ||
2. | On file created or deleted | ||
3. | Listens to the file system change notifications and raises events |