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 "edu.bit.es@gmail.com" $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.
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 "edu.bit.es@gmail.com" $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 "edu.bit.es@gmail.com" $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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.