Turning ForEach-Object into a Function

by Dec 16, 2015

ForEach-Object is a powerful pipeline cmdlet, but foremost it is an anonymous function. ForEach-Object is great to build "prototype functions" yet once you find a particular ForEach-Object statement useful, you might want to turn it into a reusable function.

The following statement uses ForEach-Object to count the elements emitted by a previous command. It uses the streaming mechanism (rather than wasting memory by first collecting all results in a variable):

Get-Service |
  ForEach-Object -Begin { $i = 0} -Process { $i++ } -End { $i }

To turn this dynamic statement into a function, simply translate it like this:

function Get-Count
    Begin { $i = 0} 
    Process { $i++ } 
    End { $i }

Get-Service | Get-Count

As you can see, the -Begin, -Process, and –End parameters are simply mapped to their respective script blocks inside the function. You can even continue to use $_ inside your function to access the streaming element. This statement returns only running services:

Get-Service | ForEach-Object { if ($_.Status -eq 'Running') { $_ } }

And here is the respective function for it:

function Get-RunningService

    if ($_.Status -eq 'Running') { $_ }

Get-Service | Get-RunningService

Why would you want to turn these pipeline statements into functions? Because it makes your code much more readable.

Pipeline cmdlets like ForEach-Object and Where-Object are perfectly fine if what you do is a very unique scenario. Once you realize, though, that the functionality you use could be useful in other scenarios as well, you might want to turn your ad-hoc pipeline cmdlets into a reusable pipeline-aware function.


Twitter This Tip! ReTweet this Tip!