This decision-making process is called pipeline parameter binding, and PowerShell has two techniques it can use: ByValue and ByPropertyName. Both of these techniques rely on the programmer who created the cmdlet having hooked it up to participate in this process.
Get-Service
Output
Stop-Service
-inputObject
?
-Name
-Exclude -Display
-Force -WhatIf
-PassThru -ConDrm
Figure 8.2 PowerShell has to decide which parameter of the second command will receive the output from the first command.
8.2 Parameter binding ByValue
With this technique, PowerShell figures out which parameters of the cmdlet are capable of accepting pipeline input ByValue. This capability, as we mentioned, is built into the cmdlet when it’s created by a programmer. The programmer decides which parameters will support the ByValue technique, and that information is docu-mented in the cmdlet’s help file. For example, if you run Help Stop-Service –Full, you can scroll down to the help for each individual parameter. Here’s what two of them look like:
-Include <string[]>
Stops only the specified services. The value of this parameter qualifies the Name parameter. Enter a name element or pattern, such as "s*". Wildcards are permitted.
Required? false Position? named Default value
Accept pipeline input? false Accept wildcard characters? false -InputObject <ServiceController[]>
Specifies ServiceController objects representing the services to be stopped. Enter a variable that contains the objects, or type a command or expression that gets the objects.
Required? true Position? 1 Default value
Accept pipeline input? true (ByValue) Accept wildcard characters? False
The –Include parameter doesn’t support pipeline input at all—it says so right in the help. The –InputObject parameter does accept pipeline input, and it does so using the ByValue technique, which is what PowerShell is attempting. PowerShell reads through all of the available parameters and figures out which ones support the ByValue technique. The result is shown in figure 8.3.
Each parameter can only accept a certain kind of input, which is also documented in the help. The –Name parameter accepts objects of the type String, whereas the -InputObject parameter accepts objects of the type ServiceController. PowerShell looks at the objects in the pipeline to see what type they are. You can do the same thing by using the Get-Member cmdlet:
PS C:\> Get-Service | Get-Member
TypeName: System.ServiceProcess.ServiceController Name MemberType Definition ----
---Name AliasProperty ---Name = Service---Name
RequiredServices AliasProperty RequiredServices = ServicesDepen...
Disposed Event System.EventHandler Disposed(Sys...
97 Parameter binding ByValue
The first line of output says it all: Get-Service produces objects of the type System .ServiceProcess.ServiceController. As a shortcut, you usually just look at the last part of the name, which is ServiceController. That’s the exact type of object that -InputObject will accept ByValue, and so, as shown in figure 8.4, PowerShell sends the objects in the pipeline to the –InputObject parameter. The help file for Stop-Service says that the –InputObject parameter
Specifies ServiceController objects representing the services to be Stopped
So whatever service objects are in the pipeline—which is all of them—will be stopped.
Get-Service
Output
Stop-Service
-inputObject
?
-Name
-Exclude -Display
-Force -WhatIf
-PassThru -ConDrm
X X X X X X
Figure 8.3 PowerShell eliminates parameters that don’t support ByValue pipeline input.
Get-Service
Output
Stop-Service
-inputObject -Name
-Exclude -Display
-Force -WhatIf
-PassThru -ConCrm
X X X X X X
Figure 8.4 The output of Get-Service will be attached to the –InputObject parameter of Stop-Service.
PowerShell always does ByValue parameter binding first; it will only go on to the next technique, ByPropertyName, if there was no parameter capable of accepting the type of object that’s in the pipeline by using the ByValue technique. You’ll also see that only one parameter per cmdlet can use ByValue. If the cmdlet had two parameters that supported ByValue, PowerShell would have no way of knowing what input gets hooked into each parameter.
NOTE PowerShell recognizes the object type “Object” as a generic type. If you look at the help for cmdlets such as Sort-Object and Select-Object, you’ll see that they too have an –InputObject parameter, which accepts pipe-line input ByValue and which accepts the generic type “Object.” In other words, any kind of object can be given to –InputObject, and that’s why all of the examples in the previous chapter worked. Parameters that accept the type
“Object” are kind of “universal recipients,” capable of accepting anything that comes along the pipeline.
8.3 Pipeline binding ByPropertyName
If PowerShell can’t make ByValue binding work, it’ll shift to Plan B, which is ByPropertyName. Let’s change our example just a bit. Take a look at figure 8.5 to see what you’ll try next (again, don’t actually run this command just yet because it might crash your machine).
You might not think it makes any sense to run Get-Service | Stop-Process, but PowerShell is going to give it a try anyway. First, the shell will look to see which param-eters accept pipeline input ByValue, and figure 8.6 shows what it comes up with.
That’s right, Stop-Process has only one parameter that accepts pipeline input ByValue, and it’s –InputObject. Unfortunately, the help file says that this parameter accepts objects of the type Process. That isn’t what you have in the pipeline, and you can’t turn a ServiceController into a Process so ByValue will fail. On to Plan B!
Get-Service
Output