The script uses file system watcher to monitor a honeypot folder, and report back any changes (edit, rename, delete or create), then performs some actions.
The actions work fine when creating, renaming and deleting.
But when editing, I can only make the script trigger the actions once. So for example, if a test device tries to edit a file on honeypot folder, the actions are triggered. But is the same device tries to edit again the same file or a different file, the watcher for editing seems to not work because the actions are not triggered.
So I tried to reset the script every 5 minutes via task scheduler (start the script every 5 minutes), but still same results.
Here's the code:
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "\\vmserver2\_Do_Not_Delete_Or_Rename"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = {
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
#Add-content "D:\log.txt" -value $logline
#write-host $logline
$targetdevice = Get-SmbOpenFile |
select clientusername, clientcomputername, path |
where {$_.Path -like 'E:\Data\Archive\_Do_Not_Delete_Or_Rename' }
$targetIP = $targetdevice.clientcomputername
$targetUser = $targetdevice.clientusername
Send-ToEmail -email "[email protected]" $targetIP
$targetUser
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 5}
I'm pretty new to powershell so I don't understand while the watchers for the rest of events work and only editing does not work.
The FileSystemWatcher lets you detect several types of changes in a directory or file, like the 'LastWrite' date and time, changes in the size of files or directories etc. It also helps you detect if a file or directory is deleted, renamed or created.
File Watcher is an IntelliJ IDEA tool that allows you to automatically run a command-line tool like compilers, formatters, or linters when you change or save a file in the IDE.
Use FileSystemWatcher to watch for changes in a specified directory. You can watch for changes in files and subdirectories of the specified directory. You can create a component to watch files on a local computer, a network drive, or a remote computer.
Your core logic is sound.
If you simplify your action block to only do the Write-host part, it should always work. I believe your problem is that on the second call, you get a terminating error that you didn't catch and in return, it stop the events from triggering.
Try replacing your action scriptblock with the following
$action = {
try {
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
#Add-content "D:\log.txt" -value $logline
#write-host $logline
$targetdevice = Get-SmbOpenFile |
select clientusername, clientcomputername, path |
where {$_.Path -like 'E:\Data\Archive\_Do_Not_Delete_Or_Rename' }
$targetIP = $targetdevice.clientcomputername
$targetUser = $targetdevice.clientusername
Send-ToEmail -email "[email protected]" $targetIP
$targetUser
}
catch {
Write-Host 'an error was thrown :(... Fortunately, it was caught.'
}
}
This should correct your issue of the changed event triggering only once.
Here's an example using 3 watchers that check for a file change over the same directory.
You will notice that after the counter reached 5, only 2 of the 3 watchers continue to work properly. The one that do not produce any errors watcherNoError
and the one that produce a terminating error but was caught in a Try catch watcherErrorsTryCatch
.
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$PathToWatch = "\\127.0.0.1\c$\_"
$watcherNoError = New-Object System.IO.FileSystemWatcher -Property @{Path = $PathToWatch;Filter = '*.*';IncludeSubdirectories=$true;EnableRaisingEvents = $true}
$watcherWithErrors = New-Object System.IO.FileSystemWatcher -Property @{Path = $PathToWatch;Filter = '*.*';IncludeSubdirectories=$true;EnableRaisingEvents = $true}
$watcherErrorsTryCatch = New-Object System.IO.FileSystemWatcher -Property @{Path = $PathToWatch;Filter = '*.*';IncludeSubdirectories=$true;EnableRaisingEvents = $true}
$Global:Counter = @{
watcherNoError = 0
watcherWithErrors = 0
watcherErrorsTryCatch = 0
}
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = {
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
Switch ($Event.MessageData.Name) {
"NoErrors" {
$Global:Counter.watcherNoError +=1
$count = $Global:Counter.watcherNoError
}
"WithErrors" {
$Global:Counter.watcherWithErrors +=1
$count = $Global:Counter.watcherWithErrors
if ($count -eq 5) {
Write-Host 'A terminated errow will be thrown...' -ForegroundColor DarkMagenta
Throw 'oh no !'
}
}
"WithErrorsTryCatch" {
$Global:Counter.watcherErrorsTryCatch +=1
$count = $Global:Counter.watcherErrorsTryCatch
if ($count -eq 5) {
try {
Throw 'oh no !'
}
catch {
Write-Host 'error was caught... You are safe ;)' -ForegroundColor Green
}
}
}
}
$logline = "Count: $Count - $($event.MessageData.Name): $changeType, $path"
write-host $logline -ForegroundColor $Event.MessageData.ForegroundColor
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcherNoError "Changed" -Action $action -MessageData @{Name='NoErrors';ForegroundColor='Yellow'}
Register-ObjectEvent $watcherWithErrors "Changed" -Action $action -MessageData @{Name='WithErrors';ForegroundColor='DarkMagenta'}
Register-ObjectEvent $watcherErrorsTryCatch "Changed" -Action $action -MessageData @{Name='WithErrorsTryCatch';ForegroundColor='Green'}
while ($true) {sleep 5}
$action = {
try {
$path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
#Add-content "D:\log.txt" -value $logline
#write-host $logline
$targetdevice = Get-SmbOpenFile |
select clientusername, clientcomputername, path |
where {$_.Path -like 'E:\Data\Archive\_Do_Not_Delete_Or_Rename' }
$targetIP = $targetdevice.clientcomputername
$targetUser = $targetdevice.clientusername
Send-ToEmail -email "[email protected]" $targetIP
$targetUser
}
catch {
Write-Host 'an error was thrown :(... Fortunately, it was caught.'
}
}
Additional note: Even if it was not the solution to your problem, you should still put a try / catch in that Action scriptblock as a terminating error will stop further processing on the next changes.
Either you'll need to use
Remove-Event $watcher "Changed"
at the end of the $Action scriptblock OR use
Unregister-Event $watcher "Changed"
Register-ObjectEvent $watcher "Changed -Action $action
at the end of the $Action scriptblock.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With