Watching the file system

We saw how to watch for WMI events http://msmvps.com/blogs/richardsiddaway/archive/2009/11/07/powershell-wmi-events.aspx. In this post we will look at watching the file system. This time we will use the .NET System.IO.FileSystemWatcher object which means we use Register-ObjectEvent instead of Register-WmiEvent.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
## folder to watch
$folder = "C:\test"
## watch all files
$filter = "*"
## events to watch
$events = @("Changed", "Created", "Deleted", "Renamed")
##
## create watcher
$fsw = New-Object -TypeName System.IO.FileSystemWatcher -ArgumentList $folder, $filter
$fsw.IncludeSubDirectories = $true
##
## register events
foreach ($event in $events){
    Register-ObjectEvent -InputObject $fsw -EventName $event -SourceIdentifier "File System $event"
}

 

We can start by defining the folder we want to watch and which files.  In this case I want to watch all files. We can restrict it to certain files e.g. $filter = “*.txt”

Wildcards work in the normal way for this filter.  We could even restrict to a single file. The events we are interested in are defined.

After creating a System.IO.FileSystemWatcher object using the folder and filter in the construction we set the IncludeSubDirectories property so we are watching the whole path.

Finally we need to register an event for each event we are interested in. Notice how the SourceIdentifier changes to identify the particular event.

We can see the Eventsubscribers we have created.

PS> Get-EventSubscriber | Select SubscriptionId, EventName, SourceIdentifier | ft -a

SubscriptionId EventName SourceIdentifier
-------------- --------- ----------------
             3 Changed   File System Changed
             4 Created   File System Created
             5 Deleted   File System Deleted
             6 Renamed   File System Renamed

We now need to perform some actions on the files – create, change, rename, delete that we are monitoring

PS> Get-Event | group SourceIdentifier

Count Name                      Group
----- ----                      -----
    7 File System Changed       {System.Management.Automation.PSEventArgs, System.Management.Automation.PSEventArgs,...
    1 File System Renamed       {System.Management.Automation.PSEventArgs}
    1 File System Created       {System.Management.Automation.PSEventArgs}
    1 File System Deleted       {System.Management.Automation.PSEventArgs}

If we look at this in more detail

PS> Get-Event | select EventIdentifier, SourceIdentifier, TimeGenerated

                        EventIdentifier SourceIdentifier                        TimeGenerated
                        --------------- ----------------                        -------------
                                      1 File System Changed                     08/11/2009 11:46:39
                                      2 File System Changed                     08/11/2009 11:46:39
                                      3 File System Renamed                     08/11/2009 11:49:53
                                      4 File System Changed                     08/11/2009 11:49:53
                                      5 File System Created                     08/11/2009 11:53:18
                                      6 File System Changed                     08/11/2009 11:53:18
                                      7 File System Changed                     08/11/2009 11:53:31
                                      8 File System Changed                     08/11/2009 11:53:31
                                      9 File System Deleted                     08/11/2009 11:54:22
                                     10 File System Changed                     08/11/2009 11:54:22

 

Note that we get pairs of events – the second event of the pair is always a change event.  If we just want to see the changes (and remove duplicates). Just be careful on this and check whether its the odd or even record you need if running multiple registered events. 

001
002
003
004
Get-Event -SourceIdentifier "File System Changed" | where {($_.EventIdentifier % 2) -eq 1} | foreach {
    "{0}, {1}, {2}" -f   $_.SourceIdentifier, $_.SourceEventArgs.FullPath, $_.TimeGenerated
   
}

 

We can use Get-Event to pull the change events from the queue. The modulo arithmetic on the EventIdentifier ensures that we only get the first change record. We can then dump the file path and time of change.

In a similar way we can interrogate the other events

001
002
003
004
Get-Event -SourceIdentifier "File System Created" | foreach {
    "{0}, {1}, {2}" -f   $_.SourceIdentifier, $_.SourceEventArgs.FullPath, $_.TimeGenerated
   
}

 

001
002
003
004
Get-Event -SourceIdentifier "File System Renamed" | foreach {
    "{0}, {1}, {2}, {3}" -f   $_.SourceIdentifier, $_.SourceEventArgs.OldFullPath, $_.SourceEventArgs.FullPath, $_.TimeGenerated
   
}

 

001
002
003
004
Get-Event -SourceIdentifier "File System Deleted" | foreach {
    "{0}, {1}, {2}" -f   $_.SourceIdentifier, $_.SourceEventArgs.FullPath, $_.TimeGenerated
   
}

 

These four could be combined into a single script if required.

Combined with the process tracing we did previously we can now track what programs are started on a system and what files are accessed.

Technorati Tags: ,,
Published Mon, Nov 9 2009 8:15 by RichardSiddaway

Leave a Comment

(required) 
(required) 
(optional)
(required)