【问题标题】:Filewatcher in Powershell not firing eventsPowershell中的Filewatcher不触发事件
【发布时间】:2022-03-22 06:29:24
【问题描述】:

希望这对 powershell 专家来说是一个快速的答案。

我有一个使用 IO.FileSystemWatcher 的 powershell 脚本。当我在 ISE 中测试我的代码而不保存文件时,文件观察器工作。但是当脚本保存在另一个位置时,它不会执行(即使在 ISE 中)。

我假设有一些执行策略阻止它。我需要做什么才能让它工作?我是管理员,我需要它在服务器上运行时才能运行。

try
{
  Write-Warning "FileSystemWatcher is monitoring $Path"
  
  # create a filesystemwatcher object
  $watcher = New-Object -TypeName IO.FileSystemWatcher -ArgumentList $Path, $FileFilter -Property @{
    IncludeSubdirectories = $IncludeSubfolders
    NotifyFilter = $AttributeFilter
  }

  # start monitoring manually in a loop:
  do
  {
    # wait for changes for the specified timeout
    # IMPORTANT: while the watcher is active, PowerShell cannot be stopped
    # so it is recommended to use a timeout of 1000ms and repeat the
    # monitoring in a loop. This way, you have the chance to abort the
    # script every second.
    $result = $watcher.WaitForChanged($ChangeTypes, $Timeout)
    # if there was a timeout, continue monitoring:
    if ($result.TimedOut) { continue }
    
    if ($RunVersion -eq "Live")
    {
        ProcessCsv -Change $result
    
    }else
    {
        ProcessCsvTest -Change $result
    }


    # the loop runs forever until you hit CTRL+C    
  } while ($true)
}
catch
{
    write-host "An error occurred"
    Write-Host $_.ScriptStackTrace
}
finally
{
  # release the watcher and free its memory:
  $watcher.Dispose()
  Write-Warning 'FileSystemWatcher removed.'
}

【问题讨论】:

  • 你怎么知道它不起作用?有错误吗?您是否尝试过捕获和写出错误?请注意,如果您不包含此信息,“它不起作用”几乎无法提供帮助。
  • 我认为您需要将enableraisingevents 设置为$True
  • @iRon,当使用同步.WaitForChanged()方法时,实际上不需要。
  • @Colyn1337 脚本运行了,但是当文件保存在我的机器上时,filesystemwatcher 片段不会执行。但它在粘贴到新的未保存的 ISE 文件并运行它时确实有效。我在测试时使用了不受限制的 Set-ExecutionPolicy 本地执行策略,但它不起作用。我感觉有一些全球政策阻止了这一点 - 几个小时后,它在没有任何代码更改的情况下工作。

标签: powershell


【解决方案1】:

除了关于您的文件系统观察程序代码

文件系统观察者的同步.WaitForChanged()方法很方便,但有两个缺点

  • 它可能会导致您错过事件:例如,如果多个文件是虚拟同时创建的,则只有一个 em> 报告事件。

  • 当方法等待时,PowerShell 不会响应 Ctrl-C,这需要在您的代码中使用周期性超时解决方法。

避免这些问题的更好的选择是使用 Register-ObjectEvent 注册文件系统更改事件,然后使用 Wait-Event在循环中同步接收事件。

下面的简化代码演示了这种方法;等待Created 事件并在收到每个事件时打印出事件详细信息:

# Sample directory path and file-name pattern to monitor.
$path = "C:\somed\dir" 
$fileFilter = '*'
  
Write-Verbose -vb "FileSystemWatcher is monitoring $path...."

try {
  
  # Create the file-system watcher instance.
  $watcher = New-Object -TypeName System.IO.FileSystemWatcher -ArgumentList $path, $fileFilter -Property @{
    IncludeSubdirectories = $false
    # NotifyFilter = ... # What attributes to monitor; by default: LastWrite, FileName, and DirectoryName - see https://docs.microsoft.com/en-us/dotnet/api/system.io.notifyfilters
  }

  # Register for (subscribe to) creation events:
  # Determine a unique event-source ID...
  [string] $sourceId = New-Guid
  # ... and register for the watcher's `Created` event with it.
  Register-ObjectEvent $watcher -EventName Created -SourceIdentifier $sourceId

  # Run indefinitely; use Ctrl-C to exit.
  while ($true) {

    # Wait (indefinitely) in blocking fashion for the next pending event.
    # Ctrl-C *does* work while waiting.
    $event = Wait-Event -SourceIdentifier $sourceId
    # The event must be manually removed from the queue.
    $event | Remove-Event
    
    # $event is an object of type [System.Management.Automation.PSEventArgs], 
    # $event.SourceArgs contains the event argument as an [object[]] array.
    # The 2nd event argument received contains the event details:
    # an object with .ChangeType, .FullPath and .Name properties.
    $eventDetails = $event.SourceArgs[1]
    
    # !! Due to an apparent bug up to at least PS 7.2,
    # !! outputting a non-primitive object whose type does NOT
    # !! have associated formatting data BLOCKS PIPELINE INPUT,
    # !! UNLESS an object WITH formatting data was output first (e.g., Get-Item /)
    # !! WORKAROUND for this demo: Use Out-Host
    $eventDetails | Out-Host

  }
}
finally {
  Write-Verbose -vb 'Cleaning up...'
  # Clean up:
  # Unregister the event subscription.
  Unregister-Event -SourceIdentifier $sourceId
  # Dispose of the watcher.
  $watcher.Dispose() 
}

【讨论】:

  • 我喜欢你对同步任务的看法。我会调查的。
【解决方案2】:

在我没有更改代码或政策后,这才重新开始工作。我相信我们的网络团队可能添加了一些我看不到的脚本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多