2015-11-27 23 views
0

我有以下代码来检测创建新文件并获取它的副本。在创建时复制文件(完成后)

$folder = '\\server\share\monitor_me\' 
$filter = '*.*' 
$copyToFolder = 'C:\temp\capture\' 

$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property @{IncludeSubdirectories = $true;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 

#protection from previous runs 
unregister-event -SourceIdentifier FileCreated -ErrorAction SilentlyContinue 

Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action { 
    $name = $Event.SourceEventArgs.Name 
    $changeType = $Event.SourceEventArgs.ChangeType 
    $timeStamp = $Event.TimeGenerated 
    Write-Host "The file '$name' was $changeType at $timeStamp" -fore green 
    Copy-Item -Path $Event.SourceEventArgs.FullPath -Destination $copyToFolder 
} 

测试符合本规则的并行会话:

1..1000 ` 
| %{new-object -TypeName pscustomobject -Property @{Id=$_;Name="hi"} } ` 
| export-csv '\\server\share\monitor_me\test.csv' 

...显示,代码完成工作;但在文件出现的时候捕获该文件,而不是等待文件完全填充,因此我只获取一些生成的文件内容。

我可以添加start-sleep声明;但那会导致竞争条件。

我认为在写入文件时会锁定文件(即阻止其他进程更新同一文件;但不影响文件的读取/复制),因此理想情况下希望有一些方法可以等待直到该锁被删除。

  • 我假设export-csv过程存在文件锁定正确吗?
  • 有没有办法检测锁何时被移除?

在此先感谢

回答

1

通过改变监视事件变化了解决。看起来2个变化事件发生在初始创建之后。为了简单起见,我只监视任何更改事件(从而确保始终拥有最新的副本),并包含-Force参数以允许覆盖目标文件。

Register-ObjectEvent $fsw Changed -SourceIdentifier FileUpdated -Action { 
    $name = $Event.SourceEventArgs.Name 
    $changeType = $Event.SourceEventArgs.ChangeType 
    $timeStamp = $Event.TimeGenerated 
    Write-Host "The file '$name' was $changeType at $timeStamp" -fore green 
    Copy-Item -Path $Event.SourceEventArgs.FullPath -Destination $copyToFolder -Force 
} 

注意:我不是100%确定这是否会捕获所有新文件;因为可能有一些方法来创建文件而不会触发更改事件(即,我还没有发现任何说明此方案不存在的文档)。但对我目前的目的来说似乎足够好。