PowerShell函数不接受对象数组

时间:2018-02-23 11:33:23

标签: function powershell parameters

在PowerShell中,我有一个需要传递给函数的对象数组。该函数然后循环遍历数组中的所有对象,但似乎它没有正确接受参数值。

采用以下示例,我传递包含两个对象的数组。我希望数组的计数在函数之前和函数内都是2,但是只要它命中函数,计数就是1,而我的输入不是预期的;只发现了最后一个对象。

我在这里遗漏了什么,或者这是PowerShell中的错误?

示例代码

### I've also tries '[object]', '[array]' and '[array[]]' as the type for '$testArr'.
function Test-PassArrayOfObjects
{
    param(
        [parameter(Mandatory,ValueFromPipeline)]
        [object[]]$testArr
    )
    Write-Host "In function count: $($testArr.Count)"
    $testArr | ForEach-Object { $_ }
}

$test1 = New-Object –TypeName PSObject
$test1 | Add-Member -MemberType NoteProperty -Name Test1 -Value Value1
$test2 = New-Object –TypeName PSObject
$test2 | Add-Member -MemberType NoteProperty -Name Test2 -Value Value2
$testArr = @($test1, $test2)

$testArr.GetType() | Format-Table
Write-Host "Before function count: $($testArr.Count)"
$testArr | Test-PassArrayOfObjects

示例代码

的输出
IsPublic IsSerial Name     BaseType                                                                                                                                                                                              
-------- -------- ----     --------                                                                                                                                                                                              
True     True     Object[] System.Array                                                                                                                                                                                          


Before function count: 2
In function count: 1

Test2 
----- 
Value2

工作修复

根据下面的答案,我有这个工作的例子,我已经能够应用到我的现实生活场景中。

function Test-PassArrayOfObjects
{
    param(
        [parameter(Mandatory,ValueFromPipeline)]
        [object]$testArr
    )
    Process {
        Write-Host "In function count: $($testArr.Count)"
        $testArr
    }
}

$test1 = New-Object –TypeName PSObject
$test1 | Add-Member -MemberType NoteProperty -Name Test1 -Value Value1
$test1 | Add-Member -MemberType NoteProperty -Name Test2 -Value Value2
$test2 = New-Object –TypeName PSObject
$test2 | Add-Member -MemberType NoteProperty -Name Test1 -Value Value1
$test2 | Add-Member -MemberType NoteProperty -Name Test2 -Value Value2
$testArr = @($test1, $test2)

$testArr.GetType() | Format-Table
Write-Host "Before function count: $($testArr.Count)"
$testArr | ForEach-Object { $_ | Test-PassArrayOfObjects }

1 个答案:

答案 0 :(得分:3)

通过管道向函数发送输入时,您的函数应包含Process块:

function Test-PassArrayOfObjects
{
    param(
        [parameter(Mandatory,ValueFromPipeline)]
        [object[]]$testArr
    )
    Process {
        Write-Host "In function count: $($testArr.Count)"
        $testArr | ForEach-Object { $_ }
    }
}

这是必要的,因为管道处理我相信的集合的方式。它会自动展开它们并一次处理一个项目,因此ForEach-Object并未将整个集合放入$testArr变量中。

你经常会看到这样的函数仍然包含ForEach,如果输入是通过参数发送的,在这种情况下它会被一次性接收。例如:Test-PassArrayOfObjects -TestArr @(1,2,3)

您的数组有两个具有不同属性的对象,这进一步加剧了您的问题。这会在输出中产生混淆,因为PowerShell决定如何根据第一个对象格式化输出,并在输出第二个对象时使用相同的格式,但是你不会看到它,因为它不会分享任何相同的属性(我认为这是正在发生的事情..)。

通过将| Format-List放在$_上,可以看到两个对象都被处理,这会强制两个输出独立地格式化为列表输出。请注意,当然,这在实际功能场景中并不是一种好的做法。另一种方法是在两个对象Test1上创建属性名称。然后,您将看到未预期的输出而不使用Format-List