JohnLBevan
JohnLBevan

Reputation: 24410

Copy File On Creation (once complete)

I have the below code to detect the creation of a new file and grab a copy of it.

$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
}

Testing it with this code in a parallel session:

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

...shows that the code does work; but captures the file the moment it appears rather than waiting for it to be fully populated, so I only get some of the resulting file's content.

I could add a start-sleep statement; but that would lead to race conditions.

I assume that there's a lock on the file whilst it's being written to (i.e. preventing other processes from updating the same file; but not affecting reading/copying of the file), so would ideally like to have some way to wait until that lock's removed.

Thanks in advance

Upvotes: 0

Views: 1881

Answers (1)

JohnLBevan
JohnLBevan

Reputation: 24410

Resolved by changing the monitored event to CHANGED. It seems 2 change events occur after the initial create. For simplicity I just monitor for any change event (thus ensuring I'll always have the latest copy) and include the -Force parameter to allow the destination file to be overwritten.

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
}

NB: I'm not 100% sure whether this will now capture all new files; as potentially there's some way to create a file without also triggering a change event (i.e. I've not found any documentation to say this scenario doesn't exist); but seems good enough for my current purposes.

Upvotes: 2

Related Questions