My actual goal is to monitor a folder for files being created and in which order they are created. Maybe there is a better tool than powershell. If so please let me know.
I took and tailored the second script here to monitor file system changes.
It uses System.IO.FileSystemWatcher to monitor the file system and fire events for certain changes in a folder.
I need to write the result to a file. First try was to pipe to Out-File. As we have tons of changes each and every second performance was very bad.
Then I took StreamWriter and and WriteLine'd the events. Performance is better know but still not perfect.
Would it make sense to use the asnchronous version of WriteLine? Or is there a even better way?
# specify the path to the folder you want to monitor:
$Path = "D:\Transfer\"
# specify whether you want to monitor subfolders as well:
$IncludeSubfolders = $true
# specify the file or folder properties you want to monitor:
$AttributeFilter = [IO.NotifyFilters]::FileName
try
{
$watcher = New-Object -TypeName System.IO.FileSystemWatcher -Property @{
Path = $Path
IncludeSubdirectories = $IncludeSubfolders
NotifyFilter = $AttributeFilter
}
# define the code that should execute when a change occurs:
$action = {
# the code is receiving this to work with:
# change type information:
$details = $event.SourceEventArgs
$FullPath = $details.FullPath
$OldFullPath = $details.OldFullPath
# type of change:
$ChangeType = $details.ChangeType
# when the change occured:
$Timestamp = ($event.TimeGenerated).ToString("yyyyMMddHHmmssffffZ")
$TimestampNow = (Get-Date).ToString("yyyyMMddHHmmssffffZ")
# now you can define some action to take based on the
# details about the change event:
# you can also execute code based on change type here:
switch ($ChangeType)
{
"Created" { $text = "{0}`t{1}`t{2}`t{3}" -f $TimestampNow, $Timestamp, $ChangeType, $FullPath }
"Deleted" { $text = "{0}`t{1}`t{2}`t{3}" -f $TimestampNow, $Timestamp, $ChangeType, $FullPath }
"Renamed" { $text = "{0}`t{1}`t{2}`t{3}`t{4}" -f $TimestampNow, $Timestamp, $ChangeType, $FullPath, $OldFullPath }
"Error" { $text = "{0}`t`t{1}" -f $TimestampNow, $ChangeType }
}
$global:SW.WriteLine($text)
$global:SW.Flush()
}
# subscribe your event handler to all event types that are
# important to you. Do this as a scriptblock so all returned
# event handlers can be easily stored in $handlers:
$handlers = . {
Register-ObjectEvent -InputObject $watcher -EventName Created -Action $action
Register-ObjectEvent -InputObject $watcher -EventName Deleted -Action $action
Register-ObjectEvent -InputObject $watcher -EventName Renamed -Action $action
}
# monitoring starts now:
$watcher.EnableRaisingEvents = $true
Write-Warning "Watching for changes to $Path"
# since the FileSystemWatcher is no longer blocking PowerShell
# we need a way to pause PowerShell while being responsive to
# incoming events. Use an endless loop to keep PowerShell busy:
do
{
# Wait-Event waits for a second and stays responsive to events
# Start-Sleep in contrast would NOT work and ignore incoming events
Wait-Event -Timeout 1
} while ($true)
}
finally
{
# this gets executed when user presses CTRL+C:
# stop monitoring
$watcher.EnableRaisingEvents = $false
# remove the event handlers
$handlers | ForEach-Object {
Unregister-Event -SourceIdentifier $_.Name
}
# event handlers are technically implemented as a special kind
# of background job, so remove the jobs now:
$handlers | Remove-Job
# properly dispose the FileSystemWatcher:
$watcher.Dispose()
$global:SW.Close()
Write-Warning "Event Handler disabled, monitoring ends."
}