Как правильно передать результаты Get-Childitem в Scriptblock?

В этом примере я пытаюсь передать результаты Get-ChildItem в сценарий, с ограниченным успехом и неожиданными результатами.

C:\temp содержит 3 файла:

  • a.txt
  • b.txt
  • C.txt

Что я хочу, чтобы пройти $files в блок скрипта здесь, и поддерживать весь список из трех файлов, которые Get-ChildItem вернулся. Другими словами, я хотел бы для $files вернуть A.txt, B.txt и C.txt как внутри, так и снаружи блока скриптов.

Я могу сделать это, но я не могу сделать это надежно, и не могу объяснить, почему. Я не хочу полагаться на "фиктивную" переменную для правильной работы, я хотел бы понять, в чем разница.

Первый пример здесь возвращает все файлы:

$files = Get-ChildItem -Path "C:\temp"
$test = $files.Get(0)
Write-Host $files.Count

Start-Job -ScriptBlock {
    Param($test, $files)
    Write-Host $files.Count
} -ArgumentList $test, $files | Out-Null

Wait-Job * | Out-Null
$results += Get-Job | Receive-Job

Второй пример только передает A.txt в блок скриптов:

$files = Get-ChildItem -Path "C:\temp"
Write-Host $files.Count

Start-Job -ScriptBlock {
    Param($files)
    Write-Host $files.Count
} -ArgumentList $files | Out-Null

Wait-Job * | Out-Null
$results += Get-Job | Receive-Job

Может кто-нибудь помочь объяснить правильный способ сделать это?

1 ответ

Решение

PowerShell разворачивает списки при передаче их в блок скриптов, так что первое значение переходит к первому параметру, второе значение ко второму параметру и т. Д. Вместо всего списка / массива, идущего к первому параметру.

В первом примере вы передаете список аргументов, который состоит из одного значения и массива значений. При развертывании этого (внешнего) списка у вас все еще есть два аргумента (одно значение и массив).

Во втором примере вы передаете только массив. Развернув этот список параметров, вы получите список из трех отдельных значений, первое из которых переходит к первому параметру блока скрипта.

Чтобы предотвратить такое поведение, вам нужно "замаскировать" одиночные массивы, поместив переменную в другой массив с помощью оператора построения унарного массива:

Start-Job -ScriptBlock {
    Param($files)
    Write-Host $files.Count
} -ArgumentList (,$files) | Out-Null

В качестве альтернативы используйте using модификатор области вместо передачи аргументов:

Start-Job -ScriptBlock {
    Write-Host $using:files.Count
} | Out-Null
Другие вопросы по тегам