簡體   English   中英

System.IO.FileSystemWatcher僅在編輯的文件上通知一次

[英]System.IO.FileSystemWatcher only notifies once on edited files

該腳本使用文件系統觀察程序監視蜜罐文件夾,並報告任何更改(編輯,重命名,刪除或創建),然后執行某些操作。

創建,重命名和刪除時,操作可以正常工作。

但是在編輯時,我只能讓腳本觸發一次動作。 因此,例如,如果測試設備嘗試編輯honeypot文件夾上的文件,則會觸發操作。 但是同一設備嘗試再次編輯同一個文件或不同的文件,編輯的觀察者似乎無法工作,因為沒有觸發操作。

所以我嘗試通過任務調度程序每5分鍾重置一次腳本(每5分鍾啟動一次腳本),但結果仍然相同。

這是代碼:

### 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}

我對powershell很新,所以我不明白,其余事件的觀察者工作,只有編輯不起作用。

你的核心邏輯是合理的。

如果將操作塊簡化為僅執行Write-host部分,則應始終有效。 我相信你的問題是,在第二次調用時,你得到一個你沒有捕獲的終止錯誤,作為回報,它會阻止事件觸發。

嘗試使用以下內容替換您的操作腳本塊

$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.'
  }
}

這應該可以解決僅觸發一次的已更改事件的問題。

這是一個使用3個觀察者的例子,它檢查同一目錄下的文件更改。 您會注意到,在計數器達到5后,3名觀察者中只有2名繼續正常工作。 沒有產生任何錯誤的watcherNoError和一個產生終止錯誤但是在Try catch watcherErrorsTryCatch捕獲的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.'
  }
}

前一個樣本的VSCode輸出

附加說明:即使它不是您的問題的解決方案,您仍應該在該Action腳本塊中放置一個try / catch,因為終止錯誤將停止對下一個更改的進一步處理。

要么你需要使用

Remove-Event $watcher "Changed"

在$ Action腳本塊的末尾或者使用

Unregister-Event $watcher "Changed"
Register-ObjectEvent $watcher "Changed -Action $action

在$ Action腳本塊的末尾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM