I'm copying files to a USB utilizing the path of the USB (assuming one drive plugged in) rather than the drive letter. I need to do it this way since I'm using this to clone 52 USBs at once.
This is where the prefix for the path is found:
$usb = Get-Volume | where {$_.DriveType -eq "Removable" }
$usb.Path
Which when concatenated with the rest of the file name becomes something like:
\\?\Volume{df4d4042-9133-11e9-9a6b-48a472473e67}\RDC_2.1.1_ALL.dmg
When I call Copy-Item
outside of a job everything works and copies properly. When I call Copy-Item
within a PowerShell job it fails and complains about the path. This doesn't make any sense to me.
Can someone tell me why my function copyFilesSync
works properly, while copyFiles
doesn't work?
For simplicity, I have cut the script back to just the elements that reproduce this issue. There is no practical difference between $filestoCopyJSON1
and $filestoCopyJSON2
. Swapping the actual files doesn't make a difference. I just needed two file names so I could run the two functions back-to-back and they were not copying the same file:
$filestoCopyJSON1 = '[
{
"FromFile": "C:\\dev\\VMware-player-12.1.1-3770994.exe",
"ToFile": "\\\\?\\Volume{df4d4042-9133-11e9-9a6b-48a472473e67}\\VMware-player-12.1.1-3770994.exe"
}
]'
$filestoCopyJSON2 = '[
{
"FromFile": "C:\\dev\\RDC_2.1.1_ALL.dmg",
"ToFile": "\\\\?\\Volume{df4d4042-9133-11e9-9a6b-48a472473e67}\\RDC_2.1.1_ALL.dmg"
}
]'
function copyFiles($filestoCopy){
Write-Host "Copying $($filestoCopy.Count)"
$copyblock = {
$copy = $args[0]
Write-Host "$($copy.FromFile)" "$($copy.ToFile)"
Copy-Item "$($copy.FromFile)" "$($copy.ToFile)"
$resultHash = Get-FileHash -LiteralPath "$($copy.ToFile)"
}
foreach ($filetoCopy in $filestoCopy) {
Start-Job -ScriptBlock $copyblock -ArgumentList @($filetoCopy)
}
Write-Host "Waiting on copying..."
Get-Job | Wait-Job
Write-Host "Files Copied"
}
function copyFilesSync($filestoCopy){
foreach ($filetoCopy in $filestoCopy) {
Copy-Item "$($filetoCopy.FromFile)" "$($filetoCopy.ToFile)"
$resultHash = Get-FileHash -LiteralPath "$($filetoCopy.ToFile)"
}
}
Remove-Job -Name *
Write-Host "Sync File Copy"
copyFilesSync -filestoCopy $(ConvertFrom-JSON -InputObject $filestoCopyJSON1)
Write-Host "Async File Copy"
copyFiles -filestoCopy $(ConvertFrom-JSON -InputObject $filestoCopyJSON2)
Receive-Job -Name *
This results in the following output:
PS C:\WINDOWS\system32> C:\dev\Test.ps1 Sync File Copy Async File Copy Copying 1 Id Name PSJobTypeName State HasMoreData Location Command -- ---- ------------- ----- ----------- -------- ------- 207 Job207 BackgroundJob Running True localhost ... Waiting on copying... 207 Job207 BackgroundJob Completed True localhost ... Files Copied C:\dev\RDC_2.1.1_ALL.dmg \\?\Volume{df4d4042-9133-11e9-9a6b-48a472473e67}\RDC_2.1.1_ALL.dmg Illegal characters in path. + CategoryInfo : NotSpecified: (:) [Copy-Item], ArgumentException + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.CopyItemCommand + PSComputerName : localhost
The first file from the Copy-Item
that's not in a job completes successfully. The async Copy-Item
run through the job fails with the errors as have been seen.