Using FileSystemWatcher to monitor a directory

Solution 1:

The problem was the notify filters. The program was trying to open a file that was still copying. I removed all of the notify filters except for LastWrite.

private void watch()
{
  FileSystemWatcher watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastWrite;
  watcher.Filter = "*.*";
  watcher.Changed += new FileSystemEventHandler(OnChanged);
  watcher.EnableRaisingEvents = true;
}

Solution 2:

You did not supply the file handling code, but I assume you made the same mistake everyone does when first writing such a thing: the filewatcher event will be raised as soon as the file is created. However, it will take some time for the file to be finished. Take a file size of 1 GB for example. The file may be created by another program (Explorer.exe copying it from somewhere) but it will take minutes to finish that process. The event is raised at creation time and you need to wait for the file to be ready to be copied.

You can wait for a file to be ready by using this function in a loop.

Solution 3:

The reason may be that watcher is declared as local variable to a method and it is garbage collected when the method finishes. You should declare it as a class member. Try the following:

FileSystemWatcher watcher;

private void watch()
{
  watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                         | NotifyFilters.FileName | NotifyFilters.DirectoryName;
  watcher.Filter = "*.*";
  watcher.Changed += new FileSystemEventHandler(OnChanged);
  watcher.EnableRaisingEvents = true;
}

private void OnChanged(object source, FileSystemEventArgs e)
{
  //Copies file to another directory.
}