The power of pipelines
The power of pipelines can best be demonstrated with a simple example:
PS:\> get-service | where-object displayName -match '^SQL Server' | set-service -startupType manual
The |
symbol indicates that these objects should be passed (aka piped) to the next cmdLet, rather than printed to the screen.
The next cmdLet is
where-object
. It applies a required condition to the objects it receives, in our case, that the value of
displayName
(which is a member of the
ServiceController
object) matches the
regular expression ^SQL Server
.
Object that satisfy this condition are (most probably) services that are related to
SQL Server.
The cmdLet discards objects that do not satisfy this condition.
Because there is yet another
|
symbol in the pipeline, PowerShell pipes the remaining object to the next cmdLet,
set-service
, to change the services'
startup type to
manual.
Such pipelines are powerful because they allow to work on a set of objects (such as services) simultaneously. Thus, they reduce human error and save time because tasks are automatable.
Last cmdlet
PowerShell automatically pipes the objects of the last cmdLet of a pipeline into the
out-default
cmdlet.
out-default
will render the
objects it receives according their
format definitions.
By default, out-default
invokes out-host
for a stream of strings.
Pipeline parameter binding
A (non-beginning) command within a pipeline needs to know which parameter will get the object from the previous command.
This is determined in a process called pipeline parameter binding.
One at a time vs All objects at once
All object at once
get-process
returns an
array of objects. Thus, the following statement prints the members of an array:
PS C:\> get-member -inputObject (get-process)
TypeName: System.Diagnostics.Process
…
One object at a time
However, when the result of get-process
is piped into another command, the command receives one object at a time. Thus, get-member
in the following pipeline prints the members of a System.Diagnostic.Process, which is the type of the objects returned by get-process
.
Because get-member
eliminates duplicates, we only see each member only once.
PS C:\> get-member -inputObject (get-process)
TypeName: System.Object[]
…
Error message: An empty pipe element is not allowed
The following simple (read: silly) pipeline will cause an An empty pipe element is not allowed error message:
foreach ($i in 1 .. 10) {
"line $i"
} | foreach-object {$_}
If such statements are put into a & { … }
or an $( … )
block, their output can be piped further down the pipeline:
& {
foreach ($i in 1 .. 10) {
"line $i"
}
} | foreach-object {$_}