I wrote a post last week about how to write functions for use in the PowerShell pipeline and I’ve been using the template I wrote in that post as the basis for several of my other scripts … and I’ve been gradually fleshing it out, and improving it, so I thought I’d drop it here with all of it’s inline comments. Hopefully that will be better than what you would get if I just trying to explain it in a blog post :) .

Incidentally, this script is also on PowerShellCentral scripts Repository where I will probably post any future modifications …


## A Template for functions which can _also_ be executed in the pipeline ....
##   by Joel Bennett, in hopes it will help...
## Version History
## v1.0 First public release (after over 9 different versions in my various other functions)
## v1.2 Show the use of Write-Output, and change "return" in the BEGIN to "Write-Output" to avoid
##      the pooling of the output from the process block when it's invoked as a function.
## v1.3 Switched back to "break" instead of "return" so that if you pass via the pipeline AND via
##      the inputObject, only the inputObject gets process (this is how cmdlets behave).
###################################################################################################
## The simplest thing is to make -inputObject the very last argument and make sure that you name
## each parameter that you expect to see ... as always you'll have to specify a value for each
## parameter, or specifically name the inputObject parameter.
##

function Test-Pipeline($Parameter1=$null, $inputObject=$null) {
     BEGIN {
      if ($inputObject) {
         ### If you're accepting $args, you need to pass those in...
         # Write-Output $io | &($MyInvocation.InvocationName) $args;
         Write-Output $inputObject | &($MyInvocation.InvocationName) $Parameter1;
         break;
      }
      else
      {  ## DO ONCE: (on the re-invoke when using -inputObject)
         Write-host "Begin $Parameter1 $args"
      }
   }
   PROCESS {
      ## You have to at least make sure it's got a value
      ## Really you should check it's TYPE to make sure you can do something useful...
      if($_) {
         Write-Host "Write-HOST: $_"
         ## You should make a practice of explicitly calling Write-Output on things
         ## That's how you emit them into the pipeline instead of just printing them
         Write-Output "Write-OUTPUT $_"
         ## Most of the time, piping to Out-Default is a lot like using Write-Host...
         "Out-Default $_" | Out-Default
      }
   }
   END {
      if (-not $inputObject)
      {  ## DO ONCE: (on the re-invoke when using -inputObject)
         $x = 0
         $args | % { $x++; "$x - $_" }
        Write-host "End"
      }
   }
}

###################################################################################################
## Sample call:
##
## [1]> Test-Pipeline Foo! @("one", "two", "three")
## Begin Foo!
## Write-HOST: one
## Write-OUTPUT one
## Out-Default one
## Write-HOST: two
## Write-OUTPUT two
## Out-Default two
## Write-HOST: three
## Write-OUTPUT three
## Out-Default three
## End

## [2]> "one", "two", "three" | Test-Pipeline Foo!
## Begin Foo!
## Write-HOST: one
## Write-OUTPUT one
## Out-Default one
## Write-HOST: two
## Write-OUTPUT two
## Out-Default two
## Write-HOST: three
## Write-OUTPUT three
## Out-Default three
## End

## ## ## To demonstrate the point of output, assign the value, or pipe it into something...
## [3]> $pipeline = "one", "two", "three" | Test-Pipeline Foo!
## Begin Foo!
## Write-HOST: one
## Out-Default one
## Write-HOST: two
## Out-Default two
## Write-HOST: three
## Out-Default three
## End

Comments are closed.