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

廉价感情. 提交于 2019-12-11 06:59:11

问题


In this example, I'm trying to pass the results of Get-ChildItem into a scriptblock, with limited success and unexpected results.

C:\temp contains 3 files:

  • A.txt
  • B.txt
  • C.txt

What I want is to pass $files into the scriptblock here, and maintain the entire list of three files that Get-ChildItem has returned. In other words, I would like for $files to return A.txt, B.txt, and C.txt, both inside and outside the scriptblock.

I am able to do this, but I'm not able to do it reliably, and cannot explain why. I do not want to have to rely on a "dummy" variable to make this work properly, I'd like to understand what the difference is.

The first example here returns all of the files:

$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

The second example only passes A.txt into the 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

Can someone help to explain the proper way to do this?


回答1:


PowerShell unrolls lists when passing them to a scriptblock, so that the first value goes to the first parameter, the second value to the second parameter, etc. instead of the entire list/array going to the first parameter.

In your first example you pass an argument list that consists of a single value and an array of values. When unrolling that (outer) list you still have two arguments (a single value and an array).

In your second example you pass just an array. When unrolling that parameter list you end up with a list of three individual values, the first of which goes to the first parameter of the scriptblock.

To prevent this behavior you need to "mask" lone arrays by wrapping the variable in another array with the unary array construction operator:

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

Alternatively use the using scope modifier instead of passing arguments:

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


来源:https://stackoverflow.com/questions/44634759/how-to-pass-results-of-get-childitem-into-a-scriptblock-properly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!