Копирование элемента с USB не работает как задание - PullRequest
0 голосов
/ 20 июня 2019

Я копирую файлы на USB, используя путь USB (при условии, что подключен один диск), а не букву диска. Мне нужно сделать это таким образом, поскольку я использую это для клонирования 52 USB одновременно.

Здесь находится префикс для пути:

$usb = Get-Volume | where {$_.DriveType -eq "Removable" }
$usb.Path

Что при объединении с остальным именем файла становится примерно таким:

\\?\Volume{df4d4042-9133-11e9-9a6b-48a472473e67}\RDC_2.1.1_ALL.dmg

Когда я звоню Copy-Item вне работы, все работает и копируется правильно. Когда я вызываю Copy-Item в задании PowerShell, он не работает и жалуется на путь. Это не имеет никакого смысла для меня.

Может кто-нибудь сказать мне, почему моя функция copyFilesSync работает правильно, а copyFiles не работает?

Для простоты я сократил сценарий только до элементов, которые воспроизводят эту проблему. Практической разницы между $filestoCopyJSON1 и $filestoCopyJSON2 нет. Обмен фактическими файлами не имеет значения. Мне просто нужно было два имени файла, чтобы я мог запускать две функции вплотную, и они не копировали один и тот же файл:

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

Это приводит к следующему выводу:

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

Первый файл из Copy-Item, который не входит в задание, завершается успешно. Асинхронный запуск Copy-Item через задание завершается с ошибками, которые были замечены.

1 Ответ

0 голосов
/ 20 июня 2019

Я считаю, что это ошибка в Powershell Jobs или Copy-Item. Я не совсем уверен, какой. Я смог обойти это, используя Background Runspaces вместо Jobs. В результате следующий асинхронный код работает нормально:

     function copyFiles($filestoCopy){
        Write-Host "Copying $($filestoCopy.Count)" 
        $copyblock = {
            $filestoCopy = $args[0]
            foreach($filetoCopy in $filestoCopy){
                Copy-Item "$($filetoCopy.FromFile)" "$($filetoCopy.ToFile)"
                $resultHash = Get-FileHash -LiteralPath "$($filetoCopy.ToFile)"

                if($filetoCopy.FromFileHash -ne $resultHash.hash){
                    Write-Host "File $($copy.ToFile) Failed.. trying again" 
                    Copy-Item "$($filetoCopy.FromFile)" "$($filetoCopy.ToFile)"
                }    
            }
        }

        $newPowerShell = [PowerShell]::Create().AddScript($copyblock).AddArgument($filestoCopy)
        $job = $newPowerShell.BeginInvoke()


        Write-Host "Waiting on copying..." 
        While (-Not $job.IsCompleted) {}
        $result = $newPowerShell.EndInvoke($job)
        $newPowerShell.Dispose()
        Write-Host "Files Copied" 
    }
...