C# utilizzo della classe FileSystemWatcher per monitorare una cartella

Articolo che fornisce una tecnica per gestire una determinata cartella.

il
Sviluppatore Microsoft .Net, Collaboratore di IProgrammatori

In questo articolo vedremo come tramite un progetto di tipo “Windows Application” si effettua il monitoraggio di una cartella, nel visualizzare a video tutti i cambiamenti che possono avvenire in una determinata cartella.
Tramite la classe FileSystemWatcher, verifichiamo se in una determinata cartella determinata file oppure tutti, vengono modificati, aggiunti, creati, rinominati o altre operazioni che si possono fare sui file e sulla cartella stessa (per esempio creazione di sottocartella).
Questo può essere utile in quei programmi che devono controllare il contenuto di una cartella oppure nell’eventualità di fare dei backup o altra funzionalità da fare sui file e cartelle.
Il progetto sarà realizzato con l’ultima versione del Framework, che in questo momento in cui stiamo scrivendo è la 7, con l’ambiente di sviluppo “Visual Studio 2022 community” e per progetto di tipo “app Windows”.

Creazione del progetto


Si crea un nuovo progetto di tipo “App Windows Forms”, selezionando come versione del “Framework” la 7 ed impostando un nome di proprio gradimento.
Terminata la creazione del progetto, non resta che aggiungere al progetto una casella di testo, con il valore impostato a “True” per la proprietà “MultiLane” e per la proprietà “Name” impostata a “TxtLog”, e coprire quasi interamente l’area della form con la casella di testo, il tutto come mostrato in figura 1.

Figura 1 – La form con la casella di testo.

Figura 1 – La form con la casella di testo.

Terminata la creazione della form non resta che scrivere il codice.

Stesura del codice


Passiamo in visualizzazione codice per scrivere il codice che dovrà monitorare una determinata cartella.
Possiamo impostare alcune proprietà della classe “FileSystemWatcher” che permette di verificare solo alcuni file oppure tutti, ed anche dire se valutare le sottocartelle.
Dopo la definizione di classe e prima del costruttore, scriviamo una variabile di classe per la gestione delle cartella. Di seguito la dichiarazione delle suddette operazioni.

C#
//Seleziono tutti i file
FileSystemWatcher FswVerificaCartella = new("C:\\Varie\\", "*.*");

Come si vede dal frammento di codice precedente, nel costruttore vengono passati due parametri, il primo il percorso della cartella da monitorare, ed il secondo che tipo di file esaminare, in questo caso tutti, nell’eventualità che erano determinati casi, occorre mettere l’estensione tipo “*.jpg” .

Nel costruttore della form, occorre impostare le notifiche che bisogna ricevere sui vari file, il gestore di evento, che viene scatenato per ogni operazione che avviene nella cartella, ed altri parametri.
Di seguito il frammento di codice delle suddette operazioni.

C#
//tipo di notifica
FswVerificaCartella.NotifyFilter = NotifyFilters.LastWrite
                   | NotifyFilters.CreationTime
                   | NotifyFilters.FileName
                   | NotifyFilters.DirectoryName
                   | NotifyFilters.Attributes
                   | NotifyFilters.Size
                   | NotifyFilters.LastWrite
                   | NotifyFilters.LastAccess
                   | NotifyFilters.CreationTime | NotifyFilters.Security;
//Gestione eventi
FswVerificaCartella.Changed += FswVerificaCartella_Changed;
FswVerificaCartella.Created += FswVerificaCartella_Created;
FswVerificaCartella.Deleted += FswVerificaCartella_Deleted;
FswVerificaCartella.Error += FswVerificaCartella_Error;
FswVerificaCartella.Renamed += FswVerificaCartella_Renamed;
//Includere sottodirettory
FswVerificaCartella.IncludeSubdirectories = true;
//gestione eventi
FswVerificaCartella.EnableRaisingEvents = true;

Come si è visto dal frammento di codice precedente, viene effettuata la gestione delle notifiche sulle varie modifiche apportate nella cartella, quale, creazione, modifica, cambio di dimensione e tanto altro. 
Inoltre per tutti gli eventi a disposizione delle classe, quale la modifica, la creazione, cancellazione, rinomina ed eventuali errori, vengono gestiti nei vari metodi.
Infine il parametro “InludeSubdirectories” impostato a true, vuol dire che verifica anche le varie sottocartelle, mentre “EnableRaisingEvents” per tenere traccia e considerazione dei vari eventi.

Di seguito si riporta il frammento di codice completo nel costruttore della classe.

C#
public Form1()
       {
           try
           {
               //tipo di notifica
               FswVerificaCartella.NotifyFilter = NotifyFilters.LastWrite
                   | NotifyFilters.CreationTime
                   | NotifyFilters.FileName
                   | NotifyFilters.DirectoryName
                   | NotifyFilters.Attributes
                   | NotifyFilters.Size
                   | NotifyFilters.LastWrite
                   | NotifyFilters.LastAccess
                   | NotifyFilters.CreationTime | NotifyFilters.Security;
               //Gestione eventi
               FswVerificaCartella.Changed += FswVerificaCartella_Changed;
               FswVerificaCartella.Created += FswVerificaCartella_Created;
               FswVerificaCartella.Deleted += FswVerificaCartella_Deleted;
               FswVerificaCartella.Error += FswVerificaCartella_Error;
               FswVerificaCartella.Renamed += FswVerificaCartella_Renamed;
               //Includere sottodirettory
               FswVerificaCartella.IncludeSubdirectories = true;
               //gestione eventi
               FswVerificaCartella.EnableRaisingEvents = true;
               //FswVerificaCartella.Filter = "*.*";
           }
           catch (Exception ex)
           {
               MessageBox.Show("Errore: " + ex.Message);
           }
           InitializeComponent();
           TxtLog.Text = "Esecuzione analizza cartella.";
       }

Ora non resta che creare i vari gestori di evento per la classe.
Con l’evento “Renamed” possiamo intercettare quando un file ed una cartella vengono rinominati, verificare il nome originale e quello nuovo, tramite le proprietà “OldName” e “Name”.
Di seguito si riporta il frammento di codice delle suddette operazioni per l’evento “Renamed

C#
private void FswVerificaCartella_Renamed(object sender, RenamedEventArgs e)
       {
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n Rinominato";
               TxtLog.Text += "\r\n Nome originario: " + e.OldName + " Percorso originario " + e.OldFullPath;
               TxtLog.Text += "\r\n nuovo nome " + e.Name + " Nuovo percorso " + e.FullPath;
           }));
       }

Per gestire eventuali eccezioni, si utilizza l’evento “Error” di seguito il frammento di codice.

C#
private void FswVerificaCartella_Error(object sender, ErrorEventArgs e)
       {
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n errore: " + e.GetException().Message;
           }));
       }

Tramite l’evento “Deleted”, possiamo gestire la situazione in cui viene cancellato un file o cartella, in tal caso verrà riportato il nome e percorso del file e cartella cancellato tramite la proprietà “FullPath”.
Di seguito il frammento di codice delle suddette operazioni.

C#
private void FswVerificaCartella_Deleted(object sender, FileSystemEventArgs e)
       {
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n cancellazione " + e.FullPath;
           }));
       }

L’evento “Created” ci permette di rilevare quando del percorso impostato viene creato un file oppure una sotto cartella, di seguito il frammento di codice per la gestione dell’evento “Created”.

C#
 private void FswVerificaCartella_Created(object sender, FileSystemEventArgs e)
       {
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n creazione : " + e.FullPath + " " + e.Name;
           }));
       }


Come per i precedenti eventi, la proprietà “fullPath” riporta il percorso completo e nome file che viene creato o sottocartella, mentre la proprietà “Name” il nome del file creato o solo il nome della sottocartella creata.
Infine siamo arrivati alla conclusione dell’articolo con l’ultimo metodo, quello relativo al cambiamento dei contenuti all’interno della cartella che abbiamo impostato nel costruttore.
Nell’evento “Changed” viene sollevato ogni qualvolta nella cartella avvengono cambiamenti, sia per i file e sia per le sottocartelle, cambiamenti che possono essere anche all’interno del file, come per esempio un file di videoscrittura, che viene salvato con nuove frasi.

C#
private void FswVerificaCartella_Changed(object sender, FileSystemEventArgs e)
       {
           if (e.ChangeType != WatcherChangeTypes.Changed)
               return;
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n" + "Cambiamento " + e.FullPath;
           }));
       }

Di seguito si riporta il frammento di codice completo di tutto l’articolo.

C#
 public partial class Form1 : Form
   {
       //Seleziono tutti i file
       FileSystemWatcher FswVerificaCartella = new("C:\\Varie\\", "*.*");
       public Form1()
       {
           try
           {
               //tipo di notifica
               FswVerificaCartella.NotifyFilter = NotifyFilters.LastWrite
                   | NotifyFilters.CreationTime
                   | NotifyFilters.FileName
                   | NotifyFilters.DirectoryName
                   | NotifyFilters.Attributes
                   | NotifyFilters.Size
                   | NotifyFilters.LastWrite
                   | NotifyFilters.LastAccess
                   | NotifyFilters.CreationTime | NotifyFilters.Security;
               //Gestione eventi
               FswVerificaCartella.Changed += FswVerificaCartella_Changed;
               FswVerificaCartella.Created += FswVerificaCartella_Created;
               FswVerificaCartella.Deleted += FswVerificaCartella_Deleted;
               FswVerificaCartella.Error += FswVerificaCartella_Error;
               FswVerificaCartella.Renamed += FswVerificaCartella_Renamed;
               //Includere sottodirettory
               FswVerificaCartella.IncludeSubdirectories = true;
               //gestione eventi
               FswVerificaCartella.EnableRaisingEvents = true;
           }
           catch (Exception ex)
           {
               MessageBox.Show("Errore: " + ex.Message);
           }
           InitializeComponent();
           TxtLog.Text = "Esecuzione analizza cartella.";
       }
       private void FswVerificaCartella_Renamed(object sender, RenamedEventArgs e)
       {
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n Rinominato";
               TxtLog.Text += "\r\n Nome originario: " + e.OldName + " Percorso originario " + e.OldFullPath;
               TxtLog.Text += "\r\n nuovo nome " + e.Name + " Nuovo percorso " + e.FullPath;
           }));
       }
       private void FswVerificaCartella_Error(object sender, ErrorEventArgs e)
       {
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n errore: " + e.GetException().Message;
           }));
       }
       private void FswVerificaCartella_Deleted(object sender, FileSystemEventArgs e)
       {
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n cancellazione " + e.FullPath;
           }));
       }
       private void FswVerificaCartella_Created(object sender, FileSystemEventArgs e)
       {
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n creazione : " + e.FullPath + " " + e.Name;
           }));
       }
       private void FswVerificaCartella_Changed(object sender, FileSystemEventArgs e)
       {
           if (e.ChangeType != WatcherChangeTypes.Changed)
               return;
           TxtLog.Invoke(new Action(delegate ()
           {
               TxtLog.Text += "\r\n" + "Cambiamento " + e.FullPath;
           }));
       }
   }

Conclusioni


L’articolo ha voluto fornire al lettore l’utilizzo della classe “FileSystemWatcher” per gestire e monitorare tutto ciò che avviene all’interno di un determinato percorso o meglio cartella.
Classe che può tornare utile per aggiungere ai propri programmi funzionalità di salvataggio dati, come un backup, oppure aspetti di sicurezza nel gestire i propri programmi e file.
Le classi messe a disposizione del framework .Net sono notevoli e semplificano di molto lo sviluppo di applicazioni ai programmatori.
La classe ed i frammenti di codice si possono utilizzare anche per applicazioni di tipo “web”, oppure con versione di Framework precedente.