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
{

  process
  {
    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!