Huddled Masses
You can do more than breathe for free...
Browse: Home / Pipeline Input vs Parameters in PowerShell scripts

Pipeline Input vs Parameters in PowerShell scripts

By Joel 'Jaykul' Bennett on 25-Apr-2008

A relatively new PowerShell user came into #PowerShell on IRC.FreeNode.net this week to ask a question about scripts and the pipeline, and the conversation went so well, that I thought I’d share it with you all in case it helps clear things up for you. We’ll call him “user” since he left before I could get his permission to paste this, and I’ve cleaned up, reordered and in a couple of cases added lines to make the conversation seem a little more linear than the chat really was.

user: Can you explain the distinction between $_ and a param in a script context?
Jaykul: I sure can. And I think I can do it simply … take an example script|function … actually, we’ll just use a scriptblock
Jaykul: it can have pipeline blocks, or not (the pipeline blocks are the BEGIN{...} PROCESS{...} END{...})
user: yeah, I’m with you
Jaykul: so if you pass a value via an argument, it’s present in all three blocks, and has the same value the whole time (unless you change it in your script)
user: really
Jaykul: But when you put that script in a pipeline, your BEGIN {} block is called first, and then for EACH item in the pipeline, powershell sets $_ and calls your PROCESS block, and finally, your END{} block is called after all pipeline items have been processed
Jaykul: Here, check this out (run it so you can see)


"one","two" | &{
BEGIN {
   foreach( $Arg in $Args )
   { Write-Host "Begin $Arg" -Fore Green }
   Write-Host "Begin (empty) Pipeline: $_" -Fore Green
}
PROCESS {
   foreach( $Arg in $Args )
   { Write-Host "Process $Arg" -Fore Cyan }
   Write-Host "Process Pipeline: $_" -Fore Cyan
}
END {
   foreach( $Arg in $Args )
   { Write-Host "End $Arg" -Fore yellow }
   Write-Host "End Pipeline: $_" -Fore Yellow
}
} "three","four" "five","six" # these are parameters to our script

user: that really helps, thank you
Jaykul: no problem. Incidentally … in a script-block like that, you can use the Params() statement, but I wanted to loop over $args ;)
user: based on that I’m left wondering what the value of parameters is.
user: If I’m writing a script, chances are that I’m going to want to use it in a pipeline
user: I guess I can use parameters, but put it in a foreach-object block
user: $arr | %{myscript $_}
Jaykul: Well, if you use the foreach-object block and pass arguments, your script doesn’t persist through the life of the pipeline, so you can’t do things like counting, or comparing to the previous object, etc.
Jaykul: But you can only pass one thing at a time via the pipeline, so you still need arguments in a script like the one I just used to paste that script to the pastebin (which is here: http://huddledmasses.org/powershell-send-paste-script/ )
user: right. So I guess the concept is that scripts grab stuff off the pipeline themselves?
Jaykul: sort-of, yeah. I mean, it’s actually PowerShell that does it, but basically, the process block grabs each item off the pipeline without needing it to be specified as an argument.

Jaykul: In v2, you can be more explicit about this, because you can write a “cmdlet” in script which lets you specify parameters which should get the pipeline value
user: okay, I totally get it now. That’s why you’d write a cmdlet instead of a script?
Jaykul: Yeah! The particularly cool thing about cmdlet parameter handling … is you can do this:
Jaykul: [Parameter(FromPipelineByPropertyValue)] [Alias(“FullName”)] $FileName
Jaykul: a parameter like that would accept a string as a parameter, but if you did gci * | scriptcmdlet instead of getting the [System.IO.FileInfo] object you would get the STRING corresponding to that object’s FullName property
user: right. sweet!
Jaykul: so you can even do tricky stuff like getting multiple properties from it (as different parameters to your script)

user: I noticed from http://powershellcentral.com/scripts/184 that you’re testing the type of the pipeline object
Jaykul: yeah
user: FIleInfo vs. string
Jaykul: because it lets me do this: ls *.ps1 | Send-Paste
Jaykul: or this: get-history -count 5 | % { $_.CommandLine } | Send-Paste
Jaykul: or even send multiple files as a single paste, like: get-content *.ps1 | Send-Paste
Jaykul: (note that in this script, that’s VERY different than ls *.ps1 | Send-Paste …. which would create a paste for each file)
user: wow, this is good stuff, thanks for the time…

Similar Posts:

  • More Custom Attributes for PowerShell (Parameter Transformation)
  • Creating WPF UIs for PowerShell with PowerBoots and Visual Studio WPF Designer
  • Parenthesis in PowerShell
  • How to: Invoke PowerShell and use the results from C#?
  • Rich formatting for PowerShell help

Posted in Huddled | Tagged Pipeline, PowerShell, PowerShell Functions

« 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.