web-dev-qa-db-fra.com

Utiliser FileSystemWatcher pour surveiller un répertoire

J'utilise une application Windows Forms pour surveiller un répertoire et déplacer les fichiers qui y sont déposés dans un autre répertoire.

Pour le moment, il copie le fichier dans un autre répertoire, mais lorsqu'un autre fichier est ajouté, il ne se termine plus par aucun message d'erreur. Parfois, il copie deux fichiers avant de finir sur le troisième.

Est-ce parce que j'utilise une application Windows Form plutôt qu'une application de console? Est-il possible d'arrêter la fin du programme et de continuer à regarder le répertoire?

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();
}
92
cheeseman

Le problème était les filtres de notification. Le programme essayait d'ouvrir un fichier en cours de copie. J'ai supprimé tous les filtres de notification, à l'exception de 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;
}
128
cheeseman

Vous n'avez pas fourni le code de gestion de fichier, mais je suppose que vous avez fait la même erreur que tout le monde lors de la première écriture: l'événement filewatcher sera déclenché dès la création du fichier. Toutefois, la finalisation du fichier prendra un certain temps. Prenez une taille de fichier de 1 Go par exemple. Le fichier peut être créé par un autre programme (Explorer.exe le copiant quelque part), mais cela prendra quelques minutes pour terminer ce processus. L'événement est déclenché au moment de la création et vous devez attendre que le fichier soit prêt à être copié.

Vous pouvez attendre qu'un fichier soit prêt en utilisant la fonction this dans une boucle.

24
nvoigt

La raison en est peut-être que watcher est déclaré en tant que variable locale par une méthode et qu'il est récupéré à la fin de la méthode. Vous devriez le déclarer en tant que membre de la classe. Essayez ce qui suit:

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