Huddled Masses
You can do more than breathe for free...
Browse: Home / Using Script Functions in the PowerShell Pipeline

Using Script Functions in the PowerShell Pipeline

By Joel 'Jaykul' Bennett on 19-Oct-2007

[new] Update, I created a better version of a pipeline function for powershell …

Every once in a while the question of how to best use the process block of a function to process pipeline objects comes up on IRC, and although I’m sure others have already written this up on the web in the past, we’ve been polishing up this example sending it back and forth to each other for a couple of weeks, and it seems to me it’s about time to publish it a little more prominently.

The basic idea was to write a function that could be used to process a set of inputs from either the pipeline or an argument, while still allowing other arguments to be passed and processed. This is something that’s very easy for a cmdlet, because you can specify that a certain parameter will receive pipeline input (and even control which attribute of the objects on the pipeline will be used), but in a script it’s not really supported. In addition, we require that the function process items as they come in, rather than waiting until it’s received all input before processing them.


function Test-Pipeline([switch]$inputObject,$io) {
    BEGIN {
        if ($inputObject) {$io | &($MyInvocation.InvocationName) $args; break;}
      $args = @($io) + $args
        Write-host "Begin $args"
    }
    PROCESS {
        write-host "PROCESSME: $_"
    }
    END {
      $x = 0
      $args | % { $x++; "$x - $_" }
       Write-host "End"
    }
}

Some explanation

This is just an example method, it doesn’t really do much, except that it outputs exactly the same thing whether you call it like Test-Pipeline -inputObject "Foo","Bar","Baz" "Kill Each Process" or like: ""Foo","Bar","Baz" | Test-Pipeline "Kill Each Process".

It works by calling itself with the inputObject argument passed on the pipeline when you specify it as an argument, so that code is processed exactly right. This means that the first line you see in the process block must remain the first line, even if you add additional code to the block.

We use a trick to make sure that additional unnamed parameters work normally by using a switch parameter -inputObject followed by a second parameter $io which we treat as inputObject if inputObject is set. This works because switch parameters don’t expect values, so we’re able to sort-of hijack it to emulate the cmdlet behavior. Note that if it is not set, we move the value of the $in parameter into the $args array which contains any additional parameters. This arrangement allows it to behave rather like a cmdlet would, but it’s a little delicate: if you’re going to pass input objects, you must specify the switch as the first argument, and pass the $io (inputObjects) immediately following (as though they were the value of the inputObjects parameter). All of that is necessary so that we can optionally pass additional parameters.

You can also add additional named parameters — but you would need to either always specify their names when you called them, or carefully adjust the code so that they get shifted if -inputObject isn’t specified.

Here’s some sample output, in case you’re wondering:


PS> $foo = "Greetings","Earthling"
PS> $foo | Template-Pipeline "Hello" "World"
Begin Hello World
PROCESSME: Greetings
PROCESSME: Earthling
1 - Hello
2 - World
End
PS> Template-Pipeline -in $foo "Hello" "World"
Begin Hello World
PROCESSME: Greetings
PROCESSME: Earthling
1 - Hello
2 - World
End
 

Credit where it’s due

I wanted to officially acknowledge that /\/\o\/\/ and Gaurhoth and Oisin and Brandon have all contributed to the polishing and testing of this script in various forms … thanks to all ;-)

Similar Posts:

  • More Custom Attributes for PowerShell (Parameter Transformation)
  • Rich formatting for PowerShell help
  • Better error messages for PowerShell ValidatePattern
  • Creating WPF UIs for PowerShell with PowerBoots and Visual Studio WPF Designer
  • Parenthesis in PowerShell

Posted in Huddled | Tagged Pipeline, PowerShell, PowerShell Functions, Scripting

« Previous Next »

Lijit Search

Tags

.Net .Net 2008 Scripting Games Automation Bugs Design Development Funny Gadgets GeoShell GUI Huddled Masses Internet licensing Microsoft Modules My Software News Personal PInvoke Pipeline Politics PoshCode PoshConsole PowerBoots PowerShell PowerShell Functions PowerTips Rants Recommender Repository Scripting ShowUI Software Solutions Textile Tips User Group UserInterface WalkThrough WebHosting Windows 7 WordPress WPF Xml

About Huddled Masses

This is web site is dedicated to the musings of Joel Bennett (aka Jaykul) about technology, software, software development, the web, and the world.

Any resemblance of the views expressed and the views of my employer, my terminal, or the view out my window are purely coincidental. The resemblance between them and my own views is non-deterministic. The question of the existence of views in the absence of anyone to hold them is left as an exercise for the reader.

P.S.: I occasionally link to things I think are great. When I do, I occasionally find a "referral code" so I can make a little cash. I promise that I don't link to anything just because of that cash (I wouldn't cross the street for the amount of cash those links bring in, never mind write a whole blog post) ... but I do not promise that things I link to will stay great as time passes, nor that you will agree with me about their greatness!

Archives

  • January 2012
  • October 2011
  • August 2011
  • July 2011
  • June 2011
  • March 2011
  • February 2011
  • January 2011
  • November 2010
  • August 2010

Copyright © 2012 Joel Bennett.

Powered by WordPress and Hybrid.