deepseapanda
deepseapanda

Reputation: 3907

Using FileSystemWatcher to monitor a directory

I am using a Windows Forms Application to monitor a directory and move the files dropped in it to another directory.

At the moment it will copy the file to another directory, but when another file is added it will just end with no error message. Sometimes it does copy two files before ending on the third.

Is this because I am using a Windows Form Application rather than a console app? Is there a way I can stop the program from ending and to keep watching the directory?

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

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

public void Dispose()
{
  // avoiding resource leak
  watcher.Changed -= OnChanged;
  this.watcher.Dispose();
}

Upvotes: 135

Views: 278162

Answers (3)

user1912419
user1912419

Reputation: 496

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.
}

Upvotes: 29

deepseapanda
deepseapanda

Reputation: 3907

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;
}

Upvotes: 182

nvoigt
nvoigt

Reputation: 77364

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.

Upvotes: 39

Related Questions