Saturday, 28 March 2015

Detecting file change management in PowerShell

For some time Windows has supported in the Win32 API various events that are triggered when files or directories in a filesystem are changed and this appears to be supported in .NET as well. This then leads us to a natural question of whether we can support that in PowerShell. Due to PowerShell being essentially a scripting extension to .NET, we indeed can use these capabilities in our scripts.

After looking on the internet it appears from several sources mentioned below I can have a script that looks something like this:
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $searchPath
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true


Starting off here the FileSystemWatcher object is instanced for this script and parameters have been passed to define the path to be searched and whether to include subdirectories. The last line tells the FileSystemWatcher to raise an event when a change is detected. 


$changed = Register-ObjectEvent $watcher "Changed" -Action {
   write-host "Changed: $($eventArgs.FullPath)"
}
$created = Register-ObjectEvent $watcher "Created" -Action {
   write-host "Created: $($eventArgs.FullPath)"
}
$deleted = Register-ObjectEvent $watcher "Deleted" -Action {
   write-host "Deleted: $($eventArgs.FullPath)"
}
$renamed = Register-ObjectEvent $watcher "Renamed" -Action {
   write-host "Renamed: $($eventArgs.FullPath)"
}
This section registers the event handlers for different types of events that are raised. Once this piece of code has executed then these actions will be fired each time the FileSystemWatcher detects a notifiable activity.

Unregister-Event $changed.Id
Unregister-Event $created.Id
Unregister-Event $deleted.Id
Unregister-Event $renamed.Id
Finishing off here with unregistering the event handlers and there should also be a call to dispose of the $watcher object or at least disable it when no longer needed. Closing the PowerShell session will have the same effect.
The source for this script came from here: http://dereknewton.com/2011/05/monitoring-file-system-changes-with-powershell/

There is a comment to that article mentioning the Change event can be fired multiple times for the same file depending on how the application doing the change works with the file. To limit the firing of multiple events some other kind of code may be needed in an event handler to determine whether the file is currently opened or closed by the application which is writing to it. I still have to do some testing with the setup I am looking at to determine how these events would be fired and which events to use. An option is to have the creating script rename the file once it has finished with it and the rename event will then be fired.

Well, testing it works more or less as expected. One major issue to be aware of is to do with errors; the code inside the braces for the Action won’t be evaluated by the Powershell ISE for syntax errors and if a mistake occurs in execution the usual messages on the Powershell console window will not be displayed. So we really only have the option of live testing. The situation I am working with uses a script that causes an email to be sent to a group whenever the action files, so I will be watching for emails coming in for sure.