FileSystemWatcher : Ecouter les modifications du système de fichiers

POWERSHELL

Dans cet article, je souhaite parler du FileSystemWatcher, une fonctionnalité .NET bien utile qui consiste à écouter les changements du système de fichier windows.
D’une manière générale, cette fonctionnalité permet d’être averti quand un changement s’opère, et d’effectuer des actions quand ce changement se produit.
L’objet FileSystemWatcher nous permet d’écouter les évènements suivants du système de fichier :

  • Changed
  • Renamed
  • Created
  • Deleted


Coté implémentation, nous devrons suivre la séquence suivante dans nos scripts:

  • Créer et configurer un objet de type filesystemwatcher
  • L’enregistrer pour écouter un évènement particulier


L’objet FileSystemWatcher

#Nous commençons par créer l'objet dans une variable :
[IO.FileSystemWatcher]$FileSystemWatcher = New-Object System.IO.FileSystemWatcher 
#Nous pouvons observer ses propriétés :
$FileSystemWatcher
FileSystemWatcher object properties
Les propriétés de l’objet FileSystemWatcher

Ci-joint la liste des principales propriétés de l’objet FileSystemWatcher et leurs descriptions respectives. Documentation complète

Path Récupère ou modifie le chemin du dossier à écouter
EnableRaisingEvents Active ou désactive le composant
FilterRécupère ou modifie le filtre d’écoute. Permet de déterminer les fichier et dossier à écouter. La valeur par défaut est « *.*

IncludeSubdirectories
Active ou désactive le fait d’écouter les sous-dossiers
InternalBufferSize Récupère ou modifie la taille du tampon interne. La valeur par defaut est 8K, doit être un multiple de 4K pour les systèmes Intel. Ne peut être inférieur à 4K
NotifyFilter Récupère ou modifie le type d’évènement à écouter


La propriété NotifyFilter


Habituellement, vous aurez à modifier le NotifyFilter, Filter, IncludeSubdirectories and Path.

Pour la propriété NotifyFilter, nous passerons par un enumérateur de type NotifyFilters. La valeur par défaut est LastWrite, FileName and DirectoryName.
Vous pouvez accéder aux valeur possibles en appellant cet énnumérateur et appuyer sur CTRL + ESPACE pour faire apparaître l’intellisense :

[System.IO.NotifyFilter]:: # CTRL + ESPACE
NotifyFilter accepted values
Valeurs du NotifyFilter

Vous trouverez en dessous les valeurs que nous pouvons suivre et leurs déscriptions respectives:

Attributes Les attributs du fichier ou dossier
CreationTimeLa date à laquelle le fichier ou dossier à été créé
DirectoryNameLe nom du dossier
FileNameLe nom du fichier
LastAccessLa date à laquelle le fichier ou dossier à été ouvert en dernier
LastWrite La date à laquelle le fichier ou dossier à été modifié en dernier
SecurityLes attributs de sécurité du fichier ou dossier
SizeLa taille du fichier ou dossier


Gardez en tête que vous pouvez écouter toute ces valeur pour un changement.
Les évènements renamed, created and deleted ne seront déclenchés que par les valeurs DirectoryName and FileName

Maintenant que nous avons fait le tour de ce concept, je vous propose de passer à des exemples complets…

Ecouter les modifications de tout les fichiers de scripts dans un dossier

#Créer un hashtable pour les propriétés de notre objet FilssystemWatcher
$param = @{
    Path = "C:\Scripts";
    Filter = "*.ps1";
    IncludeSubDirectories = $False;
    NotifyFilter = [System.IO.NotifyFilters]::FileName,[System.IO.NotifyFilters]::LastWrite
}

#Créer le FileSystemWatcher en lui passant nos propriétés
[IO.FileSystemWatcher]$scriptAccessWatcher = New-Object IO.FileSystemWatcher -property $param

#L'enregistrer pour écouter l'evenement "Changed"
#$scriptAccessWatcher | gm |?{$_.MemberType -like 'Event'} #to see the available event names
Register-ObjectEvent $scriptAccessWatcher Changed -Action {

    #Nous pouvons accéder aux propriétés de l'évènement à travers la variale $Event
    #Vous pouvez décomenter la ligne suivante pour en faire une variable globale
    #et y accéder dans la session en appellant cette variable
    #$Global:MyEventRaised = $Event
    $name = $Event.SourceEventArgs.Name
    $timeStamp = $Event.TimeGenerated   
    $changeType = $Event.SourceEventArgs.ChangeType
    Write-Host "$name has been $changeType at $timeStamp"
}
Event occurs - Output for file edition
Sortie quand un fichier est modifié

Ecouter les création de dossiers dans un dossier (et sous-dossiers)

#Créer un hashtable pour les propriétés de notre objet FilssystemWatcher
$param = @{
    Path = "C:\Scripts";
    Filter = "*.*";
    IncludeSubDirectories = $True;
    NotifyFilter = [System.IO.NotifyFilters]::DirectoryName
}

#Créer le FileSystemWatcher en lui passant nos propriétés
[IO.FileSystemWatcher]$scriptAccessWatcher = New-Object IO.FileSystemWatcher -property $param

#L'enregistrer pour écouter l'evenement "Created"
#$scriptAccessWatcher | gm |?{$_.MemberType -like 'Event'} #to see the available event names
Register-ObjectEvent $scriptAccessWatcher Changed -Action {

    #Nous pouvons accéder aux propriétés de l'évènement à travers la variale $Event
    #Vous pouvez décomenter la ligne suivante pour en faire une variable globale
    #et y accéder dans la session en appellant cette variable
    #$Global:MyEventRaised = $Event
    $name = $Event.SourceEventArgs.Name
    $timeStamp = $Event.TimeGenerated   
    $changeType = $Event.SourceEventArgs.ChangeType
    Write-Host "$name has been $changeType at $timeStamp"
}
Event occurs - Output for folder creation
Sortie quand un dossier est créé

Vous trouverez ci-dessous un moyen de vérifier sur un évènement existe déjà dans votre session

#Vous pouvez filtrer voter recherche en utilisant le SourceObject 
#qui est notre FileSystemWatcher et comparer les valeur
$objEvents = Get-EventSubscriber | ?{($_.SourceObject.Path -eq $param.Path) -and ($_.SourceObject.Filter -eq $param.Filter) -and ($_.EventName -eq 'Created')}
#Si necessaire, nous pouvons supprimer cet évènement et ne plus être notifié
$objEvents | Unregister-Event

J’utilise cette fonctionnalité .NET pour charger dynamiquement des fichiers de configuration. J’espère que ça vous donnera des idées 😉

A bientôt sur le blog !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.