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 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:
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:
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
.