【问题标题】:Pause FileSystemWatcher during action在操作期间暂停 FileSystemWatcher
【发布时间】:2020-06-29 12:35:05
【问题描述】:

我有这个 PowerShell 脚本,它可以监视文件是否已保存在文件夹中,然后调用继电器来控制交通信号灯。找到新图像后,红绿灯变为红色,等待 60 秒后变为绿色。

正如预期的那样 - 在这 60 秒内,当一个新文件添加到此文件夹时,它会进入队列 - 因此当灯变回绿色时,它们会在 60 秒内切换回红色。

在创建文件时停止 filesystemwatcher 并重新启动它的最干净的方法是什么? 当我处理 $FileSystemWatcher 时,停止 FileSystemWatcher 没问题 - 但重新启动它不起作用。此外,如果可能的话,我希望代码尽可能地冗余,而不是在我的 Action 中复制所有 FSW 代码(如果可能的话)

Write-Host "Auto Relay Change On Detection"
Add-Type -AssemblyName PresentationCore,PresentationFramework
$settingsFile = "$PSScriptRoot\settings.json"
$j = Get-Content -Raw -Path $settingsFile | ConvertFrom-Json
$PathToMonitor = $j.imageFolder

If(!(test-path $PathToMonitor))
{
      New-Item -ItemType Directory -Force -Path $PathToMonitor
}

$FileSystemWatcher = New-Object System.IO.FileSystemWatcher
$FileSystemWatcher.Path  = $PathToMonitor
$FileSystemWatcher.IncludeSubdirectories = $true

# make sure the watcher emits events
$FileSystemWatcher.EnableRaisingEvents = $true

# define the code that should execute when a file change is detected
$Action = {
    $details = $event.SourceEventArgs
    $Name = $details.Name
    $FullPath = $details.FullPath
    $OldFullPath = $details.OldFullPath
    $OldName = $details.OldName
    $ChangeType = $details.ChangeType
    $Timestamp = $event.TimeGenerated
    $text = "{0} was {1} at {2}" -f $FullPath, $ChangeType, $Timestamp

    # you can also execute code based on change type here
    switch ($ChangeType)
    {
        'Changed' { "CHANGE" }
        'Created' { "CREATED"
            $text = "File {0} was created." -f $Name
            Write-Host $text -ForegroundColor Yellow  
            Write-Host  "Relay = detected at $(Get-Date)" -ForegroundColor Yellow 
            #DO API CALL
            $timeout = $j.timer
            Start-Sleep -s $timeout
            #DO API CALL
            Write-Host  "Relay = default at $(Get-Date)" -ForegroundColor Yellow 
        }
        'Deleted' { "DELETED" }
        'Renamed' { "RENAMED" }
        default { Write-Host $_ -ForegroundColor Red -BackgroundColor White }
    }
}

# add event handlers
$handlers = . {
    Register-ObjectEvent -InputObject $FileSystemWatcher -EventName Created -Action $Action -SourceIdentifier FSCreate
}

try
{
    do
    {
        Wait-Event -Timeout 1
        ##Write-Host "." -NoNewline
        
    } while ($true)
}
finally
{
    Unregister-Event -SourceIdentifier FSCreate
    $handlers | Remove-Job
    $FileSystemWatcher.EnableRaisingEvents = $false
    $FileSystemWatcher.Dispose()
    "Event Handler disabled."
}

【问题讨论】:

  • 在开始 60 秒时设置一个标志。如果标志为真,则作为第一条声明退出您的行动。如果您忽略它的触发器,就没有理由启动和停止观察者。
  • 这是个好主意,但是(我是如何测试的)我的标志总是正确的——因为它必须在第二次 API 调用后重置,所以新图像会再次触发中继。所以在睡眠之后,flag 被设置回 1,并且只有在处理完其余的观察者队列时才读取。
  • 想一想,这里可能是 Start-Sleep 是一个错误的选择,因为整个脚本都会暂停,而不仅仅是 watcher/relay 控件。

标签: powershell filesystemwatcher


【解决方案1】:
$Action = {
    try {
        $FileSystemWatcher.EnableRaisingEvents = $false
        $details = $event.SourceEventArgs
        $Name = $details.Name
        $FullPath = $details.FullPath
        $OldFullPath = $details.OldFullPath
        $OldName = $details.OldName
        $ChangeType = $details.ChangeType
        $Timestamp = $event.TimeGenerated
        $text = "{0} was {1} at {2}" -f $FullPath, $ChangeType, $Timestamp

        # you can also execute code based on change type here
        switch ($ChangeType)
        {
            'Changed' { "CHANGE" }
            'Created' { "CREATED"
                $text = "File {0} was created." -f $Name
                Write-Host $text -ForegroundColor Yellow  
                Write-Host  "Relay = detected at $(Get-Date)" -ForegroundColor Yellow 
                #DO API CALL
                $timeout = $j.timer
                Start-Sleep -s $timeout
                #DO API CALL
                Write-Host  "Relay = default at $(Get-Date)" -ForegroundColor Yellow 
            }
            'Deleted' { "DELETED" }
            'Renamed' { "RENAMED" }
            default { Write-Host $_ -ForegroundColor Red -BackgroundColor White }
        }
    } finally {
        $FileSystemWatcher.EnableRaisingEvents = $true
    }
}

【讨论】:

  • 谢谢!做了一个有点像你的修复。 ` 'Created' { "CREATED" $FileSystemWatcher.EnableRaisingEvents = [bool] 0 #DO API CALL $timeout = $j.timer Start-Sleep -s $timeout #DO API CALL Write-Host "Relay = default at $(Get -Date)" -ForegroundColor Yellow $FileSystemWatcher.EnableRaisingEvents = [bool] 1 } ` 但你的看起来更干净。谢谢!
猜你喜欢
  • 1970-01-01
  • 2014-07-08
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多