Learning PowerCLI
上QQ阅读APP看书,第一时间看更新

Using the pipeline

In PowerShell, you can use the output of one command as input for another command by using the vertical bar (|) character. This is called using the pipeline. The vertical bar character is called the pipe character. In PowerShell, complete objects pass through the pipeline. This is different from cmd.exe or a Linux shell where only strings pass through the pipeline. The advantage of passing complete objects through the pipeline is that you don't have to perform string manipulation to retrieve property values.

Using the ByValue parameter binding

You have already seen some examples of using the pipeline in previous sections of this book, for example:

PowerCLI C:\> Get-VM | Get-Member

In this example, the output of the Get-VM cmdlet is used as the input for the Get-Member cmdlet. This is much simpler than the following command, which gives you the same result:

PowerCLI C:\> Get-Member -InputObject (Get-VM)

You can see that the Get-Member cmdlet accepts input from the pipeline if you look at the help content for the Get-Member parameter –InputObject parameter using the following command:

PowerCLI C:\> Get-Help Get-Member -Parameter InputObject

The output will be the following:

-InputObject <PSObject>
Specifies the object whose members are retrieved.
Using the InputObject parameter is not the same as piping an object to Get-Member. The differences are as follows:
-- When you pipe a collection of objects to Get-Member, Get-Member gets the members of the individual objects in the collection, such as the properties of each string in an array of strings.
-- When you use InputObject to submit a collection of objects, Get-Member gets the members of the collection, such as the properties of the array in an array of strings.
 Required? false
 Position? named
 Default value
 Accept pipeline input? true (ByValue)
 Accept wildcard characters? false

You can see in the preceding output that in the description it says Accept pipeline input? true (ByValue). This means that the Get-Member –InputObject parameter accepts input from the pipeline.

The ByValue parameter binding means that PowerShell binds the entire input object to the parameter.

In the following figure, you will see that the pipeline binds the output of the Get-Member cmdlet to the –InputObject parameter of the Get-Member cmdlet:

Using the ByValue parameter binding

Using the ByPropertyName parameter binding

If PowerShell can't find a parameter that accepts pipeline input using ByValue, it tries to find parameters that accept pipeline input using ByPropertyName. When a parameter accepts pipeline input using ByPropertyName, it means that the value of a property of the input object is bound to a cmdlet parameter with the same name as the property.

An example of a PowerShell cmdlet that accepts input from the pipeline using the ByPropertyName parameter binding is the Get-Date cmdlet, which returns a System.DateTime object. The –Date parameter of this cmdlet accepts pipeline input using both ByValue and ByPropertyName. The PowerCLI Get-VIEvent cmdlet retrieves information about the events on a vCenter Server system, for example:

PowerCLI C:\> Get-VIEvent | Select-Object -First 1


ScheduledTask : VMware.Vim.ScheduledTaskEventArgument
Entity : VMware.Vim.ManagedEntityEventArgument
Key : 64835
ChainId : 64835
CreatedTime : 12/28/2013 9:04:01 PM
UserName :
Datacenter :
ComputeResource :
Host :
Vm :
Ds :
Net :
Dvs :
FullFormattedMessage : Running task VMware vCenter Update Manager
 Check Notification on Datacenters in
 datacenter
ChangeTag :
DynamicType :
DynamicProperty :

The output has a property CreatedTime. The value of the CreatedTime property has a DateTime object type.

Let's try to pipe the output of the preceding command into the Get-Date cmdlet:

Using the ByPropertyName parameter binding

This gives an error message because the output of the Get-VIEvent cmdlet does not have a Date property that matches the –Date parameter of the Get-Date cmdlet. We will now use a calculated property to rename the CreatedTime property in Date:

PowerCLI C:\> Get-VIEvent | Select-Object -First 1 |
>> Select-Object @{Name="Date";Expression={$_.CreatedTime}} |
>> Get-Date
>>

Saturday, December 28, 2013 9:04:01 PM

Because the output of the Select-Object cmdlet has a Date property, and this property matches the Get-Date parameter –Date using the ByPropertyName parameter binding, the pipeline now works.

The following figure shows that the pipeline binds the value of the Date property in the output of the Select-Object cmdlet to the –Date property of the Get-Date cmdlet:

Using the ByPropertyName parameter binding

Most PowerCLI cmdlets will accept input from the pipeline using the ByValue parameter binding. However, only a few PowerCLI cmdlets will accept input from the pipeline using the ByPropertyName parameter binding. You can find these cmdlets with the following PowerShell code:

PowerCLI C:\> Get-VICommand |
>> Where-Object {$_.ParameterSets.Parameters |
>> Where-Object {
>> $_.ValueFromPipeline -and $_.ValueFromPipelineByPropertyName}}
>>

This is the output of the preceding command:

CommandType Name ModuleName
----------- ---- ----------
Cmdlet Add-EsxSoftwareDepot VMware.ImageBuilder
Cmdlet Add-EsxSoftwarePackage VMware.ImageBuilder
Cmdlet Compare-EsxImageProfile VMware.ImageBuilder
Cmdlet Export-EsxImageProfile VMware.ImageBuilder
Cmdlet New-EsxImageProfile VMware.ImageBuilder
Cmdlet Remove-EsxImageProfile VMware.ImageBuilder
Cmdlet Remove-EsxSoftwareDepot VMware.ImageBuilder
Cmdlet Remove-EsxSoftwarePackage VMware.ImageBuilder
Cmdlet Set-EsxImageProfile VMware.ImageBuilder

The script uses the Get-VICommand cmdlet to get all of the PowerCLI cmdlets. It then filters only those cmdlets that have parameters that accept pipeline input using ByPropertyName. As you see in the preceding output, when writing this book, only cmdlets from the PowerCLI VMware.ImageBuilder module accept pipeline input using ByPropertyName.