【问题标题】:How to pass results of Get-Childitem into a Scriptblock properly?如何正确地将 Get-Childitem 的结果传递到 Scriptblock 中?
【发布时间】:2017-06-20 00:19:00
【问题描述】:

在此示例中,我尝试将 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

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

【问题讨论】:

  • 你应该使用 foreach 循环。并迭代每个值,最后对其进行操作。
  • @Ranadip Dutta 这里的问题是,在第二个示例中,只有一个文件传递到脚本块中,尽管在我看来它的处理方式与第一个示例相同,确实通过了所有文件。

标签: powershell parameters scriptblock


【解决方案1】:

PowerShell 在将列表传递给脚本块时展开列表,以便第一个值传递给第一个参数,第二个值传递给第二个参数,依此类推,而不是整个列表/数组传递给第一个参数。

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

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

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

【讨论】:

  • 我喜欢范围界定部分。 :)
  • @Ansgar Wiechers 这正是我正在寻找的解释,非常感谢!根据我在提出问题之前尝试解决这个问题所做的测试,这个概念对我来说很有意义。这个概念对我来说是新的,所以文档非常有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 2019-03-29
  • 2015-09-08
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多