【问题标题】:Powershell - Monitoring folder ContentPowershell - 监控文件夹内容
【发布时间】:2016-05-20 15:13:24
【问题描述】:

我希望能够在短时间内监视文件夹中的更改,届时将创建大量文件并进行其他更改。

下面的代码正在运行,但没有捕捉到所有的变化。

$folder = ’C:\Data’
$timeout = 1000
$FileSystemWatcher = New-Object System.IO.FileSystemWatcher $folder
Write-Host ”Press CTRL+C to abort monitoring $folder”
while ($true) {
$result = $FileSystemWatcher.WaitForChanged(‘all’, $timeout)
if ($result.TimedOut -eq $false)
{
Write-Warning (‘File {0} : {1}’ -f $result.ChangeType, $result.name)
}
}
Write-Host ’Monitoring aborted.’

如果我在C:\Data 上使用它,它可以工作但是

我创建了一个 .txt,它显示了 2 次 new text document.txt。 然后我填写新 txt 的名称并输出 3 次。或者反过来。

请看下面的输出

  • 在我的文件夹中创建hello.txt
  • 创建一个名为 HiThere
  • 的新文件夹
  • 然后将hello.txt 重命名为someTxt.txt
  • 然后将它们都删除

输出:

`Press CTRL+C to abort monitoring C:\Data
WARNING: File Created : New Text Document.txt
WARNING: File Changed : New Text Document.txt
WARNING: File Changed : New Text Document.txt
WARNING: File Changed : hello.txt
WARNING: File Created : New folder
WARNING: File Renamed : HiThere
WARNING: File Renamed : someTxt.txt
WARNING: File Changed : someTxt.txt
WARNING: File Changed : someTxt.txt
WARNING: File Changed : someTxt.txt
WARNING: File Deleted : someTxt.txt
WARNING: File Deleted : HiThere`

更多问题:如果我在 newtwork 驱动器上使用它,则不会捕获所有更改。 (这将是这个脚本的重点,从映射驱动器监视文件夹)。

在您的机器上测试代码,只需更改文件夹路径即可。

使用 Powershell ISE 3.0

【问题讨论】:

  • 请注意,FileSystemWatcher 是出了名的不可靠,通常建议使用不同的方法来监控文件系统。
  • @GeraldSchneider 嗨,感谢您的重播。我明白了,不知道,但是也许有人有改进代码的想法。我主要是在玩 powershell 并试图找到新的很酷的方法来使用它。偶然发现了这个小项目,并想试一试。如果没有解决方案,我会放手,但还没有:)

标签: powershell directory monitoring powershell-3.0


【解决方案1】:

设置了while($true)循环,你试过“Register-ObjectEvent”吗?

我刚刚使用这种方法测试了我的一个脚本,并且可以轻松获取 2000 个空文件(在 powershell 中生成)。不幸的是,这是在本地机器上。

说明:定义正常的功能,然后离开。 你使用的命令是:

Start-BackupScript -WatchFolder "C:\temp\my watch folder\" -DestinationFolder "C:\temp\backup\"

该脚本现在监视“C:\temp\my watch folder\”以查找在该特定文件夹中创建的新文件,并将它们移动到“C:\temp\backup\”。它还将日期和时间附加到文件中。

假设您已经使用上述参数启动了脚本。您现在将“hello_world.txt”放在监视文件夹中。该脚本会将文件移动到“C:\temp\backup\”,新文件名为:“hello_world_2016-02-10_10-00-00.txt”

脚本在后台运行。如果你想知道它是怎么做的,那么使用命令:

Get-Job $backupscript -Keep

在那里你可以看到它在什么时候做了什么。请注意 -Keep 参数将输出保存在“日志”中,以便您稍后查看。

脚本:

function Start-BackupScript
{
  [CmdletBinding()]
  Param
  (
    [Parameter()]
    [String]$WatchFolder,
    [Parameter()]
    [String]$DestinationFolder
    )
  Process 
  {
    $filter = '*.*'                           
    $fsw = New-Object IO.FileSystemWatcher $WatchFolder, $filter -Property @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName,     LastWrite'} 
    $action = {
      $fileMissing = $false 
      $FileInUseMessage = $false 
      $copied = $false 
      $file = Get-Item $Args.FullPath 
      $dateString = Get-Date -format "_yyyy-MM-dd_HH-mm-ss" 
      $DestinationFolder = $event.MessageData 
      $DestinationFileName = $file.basename + $dateString + $file.extension 
      $resultfilename = Join-Path $DestinationFolder $DestinationFileName 
      Write-Output ""
      while(!$copied) { 
        try { 
          Move-Item -Path $file.FullName -Destination $resultfilename -ErrorAction Stop
          $copied = $true 
        }  
        catch [System.IO.IOException] { 
          if(!$FileInUseMessage) { 
            Write-Output "$(Get-Date -Format "yyyy-MM-dd @ HH:mm:ss") - $file in use. Waiting to move file"
            $FileInUseMessage = $true 
          } 
          Start-Sleep -s 1 
        }  
        catch [System.Management.Automation.ItemNotFoundException] { 
          $fileMissing = $true 
          $copied = $true 
        } 
      } 
      if($fileMissing) { 
        Write-Output "$(Get-Date -Format "yyyy-MM-dd @ HH:mm:ss") - $file not found!"
      } else { 
        Write-Output "$(Get-Date -Format "yyyy-MM-dd @ HH:mm:ss") - Moved $file to backup! `n`tFilename: `"$resultfilename`""
      }
    }
    $backupscript = Register-ObjectEvent -InputObject $fsw -EventName "Created" -Action $action -MessageData $DestinationFolder
    Write-Host "Started. WatchFolder: `"$($WatchFolder)`" DestinationFolder: `"$($DestinationFolder)`". Job is in: `$backupscript"
  }
}

【讨论】:

  • 我以前没有,但既然你提到它,我现在有:) 我不知道如何使用它(我只是像你说的那样替换它)。我收到这条消息supply values for the following parameters: eventName: 我应该在那里传递什么?通过快速阅读,我发现我可以使用 -MessageData parameter 在 do 块中传递一个变量。虽然不能完全解决。你是怎么做到的?
  • 我刚刚将我的脚本添加到帖子中。请注意,$action 是一个脚本块,每次创建文件时都会执行。
  • 谢谢。你能写一个简短的how to use指令附在上面吗?对于我和未来的读者
  • 我再次更新了帖子。随时提供任何反馈。
  • 通过将@{IncludeSubdirectories = $false 更改为true 并将move-item 更改为copy-item 非常接近我想要的。除了日志。我还希望有一个包含更改的日志。但是,尽管如此,您的解决方案很好,并且您得到了一个公认的答案。如果您愿意,请随时进行改进。
【解决方案2】:

你看过Register-WMIEvent吗?

类似这样的:

Register-WmiEvent -Query "SELECT * FROM __InstanceModificationEvent WITHIN 5 WHERE TargetInstance ISA 'CIM_DataFile' and TargetInstance.Path = '\\Users\\Administrator\\' and targetInstance.Drive = 'C:' and (targetInstance.Extension = 'txt' or targetInstance.Extension = 'doc' or targetInstance.Extension = 'rtf') and targetInstance.LastAccessed > '$($cur)' " -sourceIdentifier "Accessor" -Action $action   `

您可以监视文件夹,然后监视文件夹中的特定扩展。然后设置一个 PowerShell 脚本块来处理任何访问。如果您有兴趣,这里还有更多内容:https://blog.varonis.com/practical-powershell-for-it-security-part-i-file-event-monitoring/

同意上面的一些 cmets 文件监控不可靠 - 滞后和打嗝。无论如何,希望这会有所帮助。

【讨论】: