Search code examples
c#filesystemwatcher

FileSystemWatcher to monitor moved files


Possible Duplicate:
Detecting moved files using FileSystemWatcher

I'm trying to monitor moved files with the FileSystemWatcher, and got some help on the way here:

Using FileSystemWatcher with multiple files

However, I found I had to be able to use both the Deleted and the Created events in order to get the paths from where the files have been moved as well as the path to where they have been moved. But when I add similar code for the Delete event, I can only get either one or the other event to trigger. And it seems to be the order of where I wire the events that determines which event will run. So if I put the Created event last in the wiring code, that will run, and vice versa, if I put the Delete wiring last, that will run, but not Created.

Here's the code:

public class FileListEventArgs : EventArgs
{
    public List<string> FileList { get; set; }
}

public class Monitor
{
    private List<string> filePaths;
    private List<string> deletedFilePaths;
    private ReaderWriterLockSlim rwlock;
    private Timer processTimer;
    private Timer deletionTimer;
    public event EventHandler FileListCreated;
    public event EventHandler FileListDeleted;


    public void OnFileListCreated(FileListEventArgs e)
    {
        if (FileListCreated != null)
            FileListCreated(this, e);
    }

    public void OnFileListDeleted(FileListEventArgs e)
    {
        if (FileListDeleted != null)
            FileListDeleted(this, e);
    }

    public Monitor(string path)
    {
        filePaths = new List<string>();
        deletedFilePaths = new List<string>();

        rwlock = new ReaderWriterLockSlim();

        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Filter = "*.*";
        watcher.Deleted += new FileSystemEventHandler(watcher_Deleted);
        watcher.Created += watcher_FileCreated;


        watcher.Path = path;
        watcher.IncludeSubdirectories = true;
        watcher.EnableRaisingEvents = true;
    }


    private void ProcessQueue()
    {
        try
        {
            Console.WriteLine("Processing queue, " + filePaths.Count + " files created:");
            rwlock.EnterReadLock();

        }
        finally
        {
            if (processTimer != null)
            {
                processTimer.Stop();
                processTimer.Dispose();
                processTimer = null;
                OnFileListCreated(new FileListEventArgs { FileList = filePaths });
                filePaths.Clear();
            }
            rwlock.ExitReadLock();
        }
    }

    private void ProcessDeletionQueue()
    {
        try
        {
            Console.WriteLine("Processing queue, " + deletedFilePaths.Count + " files created:");
            rwlock.EnterReadLock();

        }
        finally
        {
            if (processTimer != null)
            {
                processTimer.Stop();
                processTimer.Dispose();
                processTimer = null;
                OnFileListDeleted(new FileListEventArgs { FileList = deletedFilePaths });

                deletedFilePaths.Clear();
            }
            rwlock.ExitReadLock();
        }
    }

    void watcher_FileCreated(object sender, FileSystemEventArgs e)
    {
        try
        {
            rwlock.EnterWriteLock();
            filePaths.Add(e.FullPath);

            if (processTimer == null)
            {
                // First file, start timer.
                processTimer = new Timer(2000);
                processTimer.Elapsed += (o, ee) => ProcessQueue();
                processTimer.Start();
            }
            else
            {
                // Subsequent file, reset timer. 
                processTimer.Stop();
                processTimer.Start();
            }

        }
        finally
        {
            rwlock.ExitWriteLock();
        }
    }

    void watcher_Deleted(object sender, FileSystemEventArgs e)
    {
        try
        {
            rwlock.EnterWriteLock();
            deletedFilePaths.Add(e.FullPath);

            if (deletionTimer == null)
            {
                // First file, start timer.
                deletionTimer = new Timer(2000);
                deletionTimer.Elapsed += (o, ee) => ProcessDeletionQueue();
                deletionTimer.Start();
            }
            else
            {
                // Subsequent file, reset timer. 
                deletionTimer.Stop();
                deletionTimer.Start();
            }

        }
        finally
        {
            rwlock.ExitWriteLock();
        }
    }

So how do I do this to get the original path where the files were, as well as the new path to where they have been moved? (See the first question for why the timer code is there in order to hold off the handling of the events until all files have been moved in a multifile move).


Solution

  • You declare two timers, but you only use one of them (you use the same one in the process deletion queue method). So looks like a simple copy/paste mistake to begin with.