In this article, I would like to talk about The FileSystemWatcher which is a pretty handy .NET feature that consist in monitoring file or directory changes within a specific folder.
Basically, this feature allow you configure what kind of change you would like get noticed about while your script is running, and take actions when it occurs.
The FileSystemWatcher object allow you to listen to the following events :
- Changed
- Renamed
- Created
- Deleted
To set this up, we will have to perform this sequence in our script :
- Create and configure a filesystemwatcher object
- Register this object to subscribe to a particular event
The FileSystemWatcher object
#We will start by creating the object inside a variable : [IO.FileSystemWatcher]$FileSystemWatcher = New-Object System.IO.FileSystemWatcher #We can have a look at its properties in order to figure out what we need to care about $FileSystemWatcher

Here is the list of the main FileSystemWatcher parameters with their respective descriptions. Full documentation
Path | Sets or Gets the Path of the directory to watch |
EnableRaisingEvents | Enable or disable the component |
Filter | Gets or sets the filter string, used to determine what files are monitored in a directory. Default value is (*.*) |
IncludeSubdirectories | Enables or disables including subdirectories to be watched |
InternalBufferSize | Gets or sets the size of internal buffer. Default is 8K, should be a multiple of 4k for best performances on intel based hardware. It could not be lower than 4K. |
NotifyFilter | Gets or sets the type of changes to watch for |
The NotifyFilter property
Usually, you will configure NotifyFilter, Filter, IncludeSubdirectories and Path.
For the NotifyFilter property, you will have to use NotifyFilters enumeration. The default value is set to LastWrite, FileName and DirectoryName.
You can access the possible values by calling this .NET enumerator and pressing CTRL + SPACE to force the intellisense :
[System.IO.NotifyFilters]:: # CTRL + SPACE

Here are the values you can monitor with their respective descriptions :
Attributes | The attributes of the file or folder |
CreationTime | The time the file or folder was created |
DirectoryName | The name of the directory |
FileName | The name of the file |
LastAccess | The date the file or folder was last opened |
LastWrite | The date the file or folder last had anything written to it |
Security | The security settings of the file or folder |
Size | The size of the file or folder |
Bear in mind that you can monitor all of the values above for a Change.
Renamed, created and deleted events will fire only from the DirectoryName and FileName values
Now that we understand how this concept works, let’s take some full examples…
Watch changes in all script file in a directory
#Create a hashtable for our FileSystemWatcher object properties $param = @{ Path = "C:\Scripts"; Filter = "*.ps1"; IncludeSubDirectories = $False; NotifyFilter = [System.IO.NotifyFilters]::FileName,[System.IO.NotifyFilters]::LastWrite } #Create the .NET FileSystemWatcher object and passing our properties [IO.FileSystemWatcher]$scriptAccessWatcher = New-Object IO.FileSystemWatcher -property $param #Register the object to the Changed Event #$scriptAccessWatcher | gm |?{$_.MemberType -like 'Event'} #to see the available event names Register-ObjectEvent $scriptAccessWatcher Changed -Action { #The event raised properties can be accessed with the $Event variable #You can uncomment the line bellow to make it a global variable #and access it in your session by typing the variable name #$Global:MyEventRaised = $Event $name = $Event.SourceEventArgs.Name $timeStamp = $Event.TimeGenerated $changeType = $Event.SourceEventArgs.ChangeType Write-Host "$name has been $changeType at $timeStamp" }

Watch folder creation in a directory (and subdirectories)
#Create a hashtable for our FileSystemWatcher object properties $param = @{ Path = "C:\Scripts"; Filter = "*.*"; IncludeSubDirectories = $True; NotifyFilter = [System.IO.NotifyFilters]::DirectoryName } #Create the .NET FileSystemWatcher object and passing our properties [IO.FileSystemWatcher]$FolderCreationWatcher = New-Object IO.FileSystemWatcher -property $param #Register the object to the Created Event #$scriptAccessWatcher | gm |?{$_.MemberType -like 'Event'} #to see the available event names Register-ObjectEvent $FolderCreationWatcher Created -Action { #The event raised properties can be accessed with the $Event variable #You can uncomment the line bellow to make it a global variable #and access it in your session by typing the variable name #$Global:MyEventRaised = $Event $name = $Event.SourceEventArgs.Name $timeStamp = $Event.TimeGenerated $changeType = $Event.SourceEventArgs.ChangeType Write-Host "$name has been $changeType at $timeStamp" }

Additionally, here is a way to check if an event already exists in your session :
#You can filter event using the SourceObject which is our FileSystemObject and compare values $objEvents = Get-EventSubscriber | ?{($_.SourceObject.Path -eq $param.Path) -and ($_.SourceObject.Filter -eq $param.Filter) -and ($_.EventName -eq 'Created')} #If necessary, we can unregister this event se we will not get noticed anymore $objEvents | Unregister-Event
I like to use this .NET feature to dynamically load configuration files. I hope that it gave you some ideas đ
See you soon in the blog !
Comments
Thanks for that list of properties. Knew there were more than the 3 or 4 listed on MS, but couldn’t find them. Spent more time than I am willing to admin trying to find the Last Access Time.
Should it be [System.IO.NotifyFilters] and not [System.IO.NotifyFilter]
Author
Hey, glad you spotted it.
Corrected ! Many thanks