如何正确地将Get-Childitem的结果传递给Scriptblock?

时间:2017-06-19 15:42:48

标签: powershell parameters 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传递给scriptblock:

$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 个答案:

答案 0 :(得分:2)

PowerShell在将它们传递给scriptblock时展开列表,以便第一个值转到第一个参数,第二个值转到第二个参数等,而不是整个列表/数组转到第一个参数。

在第一个示例中,您传递的参数列表包含单个值和值数组。展开该(外部)列表时,您仍然有两个参数(单个值和一个数组)。

在第二个示例中,您只传递一个数组。展开该参数列表时,最终会得到一个包含三个单独值的列表,第一个值将转到scriptblock的第一个参数。

要防止出现这种情况,您需要通过使用unary array construction operator将变量包装到另一个数组中来“屏蔽”单个数组:

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

或者使用using scope modifier而不是传递参数:

Start-Job -ScriptBlock {
    Write-Host $using:files.Count
} | Out-Null