Powershell FileSystemWatcher-避免在创建时重复操作

时间:2019-05-21 22:14:22

标签: powershell filesystemwatcher

PowerShell中的一个已知问题是FileSystemWatcher在事件上触发两次。我正在尝试解决此问题,因为我正在查看正在创建的文件,然后将其推送到打印机。两次触发意味着我得到了重复的打印输出

我知道之前曾有人问过这个问题,但是当我谈到Powershell时(对于一般的脚本来说)我是一个新手,所以有些答案直指我了

在代码中,我正在监视一个文件夹,然后将子目录名称作为发送作业的打印机名称传递。这是因为使用的软件正在将pdf文件从远程位置复制到这些文件夹中(由于citrix,该软件无法直接访问打印机)

### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "L:\Label\"
    $watcher.Filter = "*.*"
    $watcher.IncludeSubdirectories = $true
    $watcher.EnableRaisingEvents = $true 

### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
    $action = { $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $printer = Split-Path (Split-Path $path -Parent) -Leaf
                $logline = "$(Get-Date), $changeType, $path, $printer"
                Add-content "c:\prog\log.txt" -value $logline
                C:\prog\SumatraPDF.exe -print-to "\\http://srv:631\$printer" $path
              }    

### DECIDE WHICH EVENTS SHOULD BE WATCHED 
    Register-ObjectEvent $watcher "Created" -Action $action
    while ($true) {sleep 5}

我希望仅在将pdf文件放入监视文件夹时看到打印命令(苏门答腊呼叫)仅发生一次

2 个答案:

答案 0 :(得分:0)

我认为FileSystemWatcher在事件(而不是在何处获得该信息)上触发两次不是已知问题。

无论如何,如果我还是我自己,都不会在Powershell中编写FileSystemWather事件的代码,这确实很痛苦。

相反,您可以使用Powershell Guard,只需传递print命令而不是TestCommand。 https://github.com/smurawski/PowerShellGuard

PowerGuard所做的只是抽象使用FileSystemWatcher。您可以在Powershell脚本中创建打印命令,只需让PowerGuard使用-TestCommand“ Print.ps1。\ PathToYourFile”来调用脚本

最终解决方案(由发布者本人完成):

dir \\srv\label\prnlblCuts\*.pdf | New-Guard -TestCommand "C:\PROG\SumatraPDF.exe -print-to \\srv-tsv:631\prnlblCuts" -TestPath "$($_.FullName)" -Wait

答案 1 :(得分:0)

这里不是告诉您应该做什么或不应该做什么,而是按照您的要求去做:

sfml

在检测到事件后定义操作

### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$global:canDoEvent = $True #NEW
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "L:\Label\"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true 

决定应该关注哪些事件

$action = { if ($global:canDoEvent) { #NEW
                $global:canDoEvent = $False #NEW
                $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $printer = Split-Path (Split-Path $path -Parent) -Leaf
                $logline = "$(Get-Date), $changeType, $path, $printer"
                Add-content "c:\prog\log.txt" -value $logline
                C:\prog\SumatraPDF.exe -print-to "\\http://srv:631\$printer" $path
            }
          }    

它可能需要调整,我不是专家,但这就是想法。

基本上,添加一个全局布尔值 var = True,将您的等待事件置于 do-while 循环内的超时状态,在每个循环中将变量设为真,然后在您的事件操作中将其设为假。您的超时将定义事件触发的频率。一秒钟就足以防止多次触发事件。显然,如果存在可以在同一秒内创建和打印 1 个以上唯一文件的上下文,它会跳过它们。