PowerShell高级函数输出PipelineVariable不起作用

时间:2017-08-20 12:53:22

标签: function powershell pipeline cmdlet

我创建了一个高级功能,用于从运行在VMware ESXi上的VM获取mac地址。

function Get-MacFromVm {
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
        # The name of the VM of which we want to obtain the mac address.
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)]
        [string[]]
        $Name
    )

    Begin {}
    Process {
        foreach ($item in $Name) {
            if ($PSCmdlet.ShouldProcess($item, "Getting the mac address")) {
                Get-VM $item -PipelineVariable vm | 
                    Get-NetworkAdapter | 
                    Select-Object @{n="Name"; e={$vm.Name}},
                        @{n="ClientId"; e={$_.MacAddress -replace ":","-"}}
            }
        }  
    }
    End {}
}

到目前为止,一切都很完美。 我可以通过以下任何一种方式使用它并获得结果。

它通过命名参数或管道输入接受单个或数组字符串。

Get-MacFromVm -Name "playground"
Get-MacFromVm -Name "playground", "DC01"
"playground", "DC01" | Get-MacFromVm

输出是[PSCustomObject],有2个属性,一个是Name和ClientId。

现在,当我想使用-PipelineVariable参数将结果链接到多个其他cmdlet时,问题就开始了。

通常我应该能够像这样使用它:

Get-MacFromVm -Name "playground" -PipelineVariable pv | % {$pv}

但它没有向我显示任何结果。如果我用$pv代替$_它确实显示了正确的结果,但我不能在管道链中使用更远的自动变量2或3个cmdlet。

虽然我可以使用-OutVariable和/或将其分成多行来解决这个问题。 我想知道为什么这不起作用,我想知道我在这里缺少什么。

1 个答案:

答案 0 :(得分:0)

我没有使用-PipelineVariable参数的经验。因此,我以此为契机,了解-PipelineVariable参数:

由于我也无法轻松访问虚拟机,因此我按如下方式模拟了该功能:

Function Get-MacFromVm {
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)]
        [string[]]
        $Name
    )
    Function MacAddress {(1..4 | ForEach {'{0:x2}' -f (Get-Random -Min 0 -Max 255)}) -Join ":"}
    Function Get-VM {[cmdletbinding()] Param ($Name) [pscustomobject]@{Name = $Name; MacAddress = (MacAddress)}}
    ForEach ($Item in $Name) {
        If ($PSCmdlet.ShouldProcess($Item, "Getting the mac address")) {
            Get-VM $item -PipelineVariable vm |
            Select-Object @{n="Name"; e={$vm.Name}}, @{n="ClientId"; e={$_.MacAddress -replace ":","-"}}
        }
    }
}

但我无法重现这个问题:

PS C:\> Get-MacFromVm -Name "playground", "DC01" -PipelineVariable pv | % {$pv}

Name       ClientId
----       --------
playground 3c-23-55-c4
DC01       4f-38-42-a7

所以我想知道这个模拟功能是否适合你。
如果是,也许您可​​以找到与真实VM对象的差异。

了解PowerShell,我会质疑是否没有输出或没有显示。那么如果您只输出一个属性会发生什么:

Get-MacFromVm -Name "playground" -PipelineVariable pv | % {$pv.Name}

或者:

Get-MacFromVm -Name "playground" -PipelineVariable pv | % {$pv.GetType()}

这会返回" You cannot call a method on a null-valued expression."错误?