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

How to pass results of Get-Childitem into a Scriptblock properly?

在此示例中,我尝试将 Get-ChildItem 的结果传递到脚本块中,但成功率有限且结果意外。

C:\temp 包含 3 个文件:

我想要的是将 $files 传递到这里的脚本块中,并维护 Get-ChildItem 已 return 编辑的三个文件的完整列表。换句话说,我想要 $files 到 return A.txt、B.txt 和 C.txt,脚本块内部和外部。

我可以做到这一点,但我无法可靠地做到这一点,也无法解释原因。我不想依赖 "dummy" 变量来使它正常工作,我想了解其中的区别。

此处的第一个示例 return所有文件:

$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

有人可以帮忙解释一下正确的方法吗?

PowerShell 在将列表传递给脚本块时展开列表,以便第一个值传递给第一个参数,第二个值传递给第二个参数,等等,而不是整个 list/array 传递给第一个参数.

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

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

为了防止这种行为,您需要 "mask" 通过使用 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