2011-08-05 4 views
1

Possible en double:
Detecting moved files using FileSystemWatcherFileSystemWatcher pour surveiller les fichiers déplacés

Je suis en train de surveiller les fichiers évolué avec le FileSystemWatcher, et a obtenu une aide sur le chemin ici:

Using FileSystemWatcher with multiple files

Cependant, j'ai trouvé que je devais être abl e pour utiliser à la fois les événements Supprimé et Créé afin d'obtenir les chemins d'où les fichiers ont été déplacés ainsi que le chemin d'accès où ils ont été déplacés. Mais lorsque j'ajoute un code similaire pour l'événement Delete, je ne peux déclencher que l'un ou l'autre événement. Et il semble que ce soit l'ordre dans lequel je fil les événements qui détermine quel événement va se dérouler. Donc, si je mets l'événement Created en dernier dans le code de câblage, cela fonctionnera, et vice versa, si je mets le dernier Delete, cela fonctionnera, mais pas Created.

Voici le 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(); 
     } 
    } 

Alors, comment puis-je faire pour obtenir le chemin d'origine où les fichiers étaient, ainsi que le nouveau chemin à l'endroit où ils ont été déplacés? (Voir la première question pour savoir pourquoi le code de la minuterie est là afin de retarder le traitement des événements jusqu'à ce que tous les fichiers aient été déplacés dans un mouvement multifil).

+0

Je ne pense pas. Je n'ai aucun problème avec l'utilisation du nom de fichier pour comparer les fichiers, comme dans ce post. Le problème est que je ne peux pas supprimer et créer des événements à déclencher. Ou du moins tout ce que je vois est que l'événement create est déclenché et que la suppression n'a pas encore eu lieu. Dans ma classe principale, je dois prendre la liste des fichiers créés et la comparer à la liste des fichiers supprimés, mais la liste des fichiers supprimés est vide, tandis que la liste des fichiers créés est remplie. – Anders

Répondre

1

Vous déclarez deux minuteurs, mais vous n'en utilisez qu'un (vous utilisez le même dans la méthode de la file d'attente de suppression de processus). Cela ressemble donc à une simple erreur copier/coller pour commencer.

+0

Merci, c'était une tentative de ma part pour le faire fonctionner, mais j'ai manqué de changer certaines choses avec le copier-coller comme vous l'avez dit. Cela n'a cependant pas aidé à corriger cette erreur, mais cela m'a permis de le revoir et j'ai découvert que si j'ai déclenché les deux événements dans la même méthode ProcessQueue, cela a fonctionné, donc je vous créditerai pour cela. – Anders

0

J'ai découvert que les événements FileSystemWatcher ne sont PAS mis en file d'attente (caveat: c'était il y a environ 8 ans).

Si vous traitez un fichier et que 3 nouveaux fichiers sont créés lors du traitement, vous n'obtiendrez pas les 3 événements. Après le traitement d'un fichier, vous devrez peut-être vérifier manuellement le répertoire pour d'autres modifications.

+0

Eh bien, j'obtiens 3 événements pour le déplacement de 3 fichiers ... Mais le problème est que je n'arrive pas à déclencher l'événement delete et l'événement create, seulement l'un ou l'autre. – Anders

+0

Surveillez-vous un seul répertoire? Si vous déplacez un fichier, il ne peut pas rester dans le même répertoire. Si un fichier est déplacé, vous obtiendrez l'événement supprimé. Si un fichier est déplacé, vous obtenez l'événement créé. Je ne vois pas comment vous pourriez obtenir les deux. –

Questions connexes