<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Huddled Masses &#187; Pipeline</title>
	<atom:link href="http://huddledmasses.org/tag/pipeline/feed/" rel="self" type="application/rss+xml" />
	<link>http://huddledmasses.org</link>
	<description>You can do more than breathe for free...</description>
	<lastBuildDate>Sat, 28 Jan 2012 21:37:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<cloud domain='huddledmasses.org' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>PowerShell: Determine your function&#8217;s position in the pipeline</title>
		<link>http://huddledmasses.org/powershell-determine-your-functions-position-in-the-pipeline/</link>
		<comments>http://huddledmasses.org/powershell-determine-your-functions-position-in-the-pipeline/#comments</comments>
		<pubDate>Mon, 28 Dec 2009 02:54:33 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PowerShell Functions]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1362</guid>
		<description><![CDATA[I just posted an article to the FAQ on the PoshCode Wiki answering this question that came up again on our IRC PowerShell user group today. It came up in the context of determining whether a function was the last function on the pipeline, because one of our users was looking for a way (other [...]]]></description>
			<content:encoded><![CDATA[	<p>I just posted an article to the <a href="http://wiki.poshcode.org/index.php?title=FAQ/Tips_and_Tricks/How_Do_I..._Determine_My_Function%27s_Position_in_the_Pipeline"><span class="caps">FAQ</span> on the PoshCode Wiki</a> answering this question that came up again on our <span class="caps">IRC</span> <a href="http://PowerShellGroup.org/virtual">PowerShell user group</a> today. It came up in the context of determining whether a function was the last function on the pipeline, because one of our users was looking for a way (other than creating ps1xml files) to output objects onto the pipeline for use in other functions, but still format those objects nicely if they were output directly. </p>

	<p>Before I give the solution, I just want to say: <strong>don&#8217;t change your output based on where you are in a pipeline.</strong></p>

	<p>There are numerous scenarios where your function will be the last one on a pipeline, but still be participating in further pipelines, including formatting and output modification. For example, take our function Test-Pipeline (defined below) in these three scenarios below. In none of these scenarios would it be appropriate for the function to write formatted output instead of outputting the raw object, but in each case, the function <strong>is</strong> the last function in the pipeline.</p>

	<div class="poshcode code poshcode" style="font-family:monospace;"><br />
# Assignment<br />
$order = Get-ChildItem | Test-Pipeline<br />
$order | Format-Table *<br />
<br />
# Nested Pipelines<br />
Get-ChildItem | Where-Object { $_.PsIsContainer} | ForEach-Object {<br />
Get-ChildItem $_ | Test-Pipeline<br />
} | Select-Object Pipe*<br />
<br />
# Nested Expressions<br />
@( Get-ChildItem | Test-Pipeline )[0].PipelineLength | ForEach-Object { $_ }<br />
&nbsp;</div>

	<p>However, if you want to determine your function&#8217;s position in the pipeline for some other reason, the answer is simple. You need to use <code>$MyInvocation</code> and compare the <code>PipelineLength</code> and <code>PipelinePosition</code> properties:</p>

	<div class="poshcode code poshcode" style="font-family:monospace;"><br />
## Useful for testing all sorts of things about the pipeline<br />
function Test-Pipeline {<br />
[CmdletBinding()]<br />
Param(<br />
&nbsp; &nbsp;[Parameter(ValueFromPipeline=$true)]<br />
&nbsp; &nbsp;[PSObject]$InputObject,<br />
&nbsp; &nbsp;[Switch]$Passthru,<br />
&nbsp; &nbsp;[Switch]$PassCmdlet<br />
)<br />
BEGIN { <br />
&nbsp; &nbsp;Write-Output $MyInvocation<br />
&nbsp; &nbsp;if($PassCmdlet) {<br />
&nbsp; &nbsp; &nbsp; Write-Output $PsCmdlet<br />
&nbsp; &nbsp;}<br />
}<br />
PROCESS { if($Passthru){ $_ } }<br />
}<br />
<br />
## Shows <br />
function Test-LastInPipeline {<br />
Param(<br />
&nbsp; &nbsp;[Parameter(ValueFromPipeline=$true)]<br />
&nbsp; &nbsp;[PSObject]$InputObject,<br />
&nbsp; &nbsp;[Switch]$Passthru<br />
)<br />
BEGIN { <br />
&nbsp; &nbsp;$IsLast = $MyInvocation.PipelineLength -eq $MyInvocation.PipelinePosition<br />
&nbsp; &nbsp;if(!$IsLast) { $MyInvocation }<br />
}<br />
PROCESS { if($Passthru){ $_ } }<br />
}<br />
&nbsp;</div>

<div class="zemanta-pixie"><a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/d70821bd-4e06-4fc1-81f4-451e14c63c2f/" title="Reblog this post [with Zemanta]"><img class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=d70821bd-4e06-4fc1-81f4-451e14c63c2f" alt="Reblog this post [with Zemanta]" /></a><span class="zem-script more-related pretty-attribution"><script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"></script></span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/powershell-determine-your-functions-position-in-the-pipeline/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using Script Functions in the PowerShell Pipeline ( Take Two )</title>
		<link>http://huddledmasses.org/using-script-functions-in-the-powershell-pipeline-take-two/</link>
		<comments>http://huddledmasses.org/using-script-functions-in-the-powershell-pipeline-take-two/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 13:07:27 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Advanced Functions]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PowerShell Functions]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/using-script-functions-in-the-powershell-pipeline-take-two/</guid>
		<description><![CDATA[One of the consistent questions about PowerShell is: what&#8217;s the best way to write a script or a function to process pipeline objects and be able to take it&#8217;s parameters as a normal function? Of scripts and functions The first thing to know is that in PowerShell, there&#8217;s really no difference between a script (just [...]]]></description>
			<content:encoded><![CDATA[	<p>One of the consistent questions about PowerShell is: what&#8217;s the best way to write a script or a  function to process pipeline objects <em>and</em> be able to take it&#8217;s parameters as a normal function?</p>

	<h3>Of scripts and functions</h3>

	<p class="em1">The first thing to know is that in PowerShell, there&#8217;s really no difference between a script (just a file with a .ps1 ending) and a function as you&#8217;ll see written below. If you take a function Get-Square, and remove the first and last lines (<code> Function Get-Square { </code> &#8230; <code> } </code>) you could put them in a file called &#8220;Get-Square.ps1&#8221; in your <span class="caps">PATH</span>, you use them exactly the way you would the function that was pre-loaded into memory by dot-sourcing or pasting it on the command line.  Of course, doing that easily requires writing the function parameters on their own line using <code>PARAM(...)</code> syntax, which is why I recommend doing that.</p>

	<h3>Of functions and the pipeline</h3>

	<p>When your script or function is used on the pipeline its <code>begin</code> block is called <em>once</em> when the pipeline starts up, and then the <code>process</code> block is called repeatedly: once to <em>process</em> each pipeline object, and finally, the <code>end</code> block is called after all the objects have been processed through the whole pipeline.  If you don&#8217;t understand that, you should play with this function, try calling it by passing a series of numbers through multiple instances of it:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquarePipe</span></span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">PARAM</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$label</span>, <span style="color: #660033; font-weight: bold;">$color</span><span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;White&quot;</span> <span style="color: #333;">&#41;</span> <br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">BEGIN</span> &nbsp; <span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Begin $Label&quot;</span> <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">PROCESS</span> <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;$Label <span style="color: #000099; font-weight: bold;">`t</span> $_&quot;</span> <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$_</span> <span style="color: #66cc66;">*</span> <span style="color: #660033; font-weight: bold;">$_</span> <br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">END</span> &nbsp; &nbsp; <span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;End $Label&quot;</span> &nbsp; <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span> <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># for example ...</span><br />
1..5 <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquarePipe</span></span> one cyan <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquarePipe</span></span> two yellow <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquarePipe</span></span> three green<br />
&nbsp;</div>

	<p style="padding-left:2em;">Incidentally, if you don&#8217;t specify the <code>begin</code>, <code>process</code>, or <code>end</code> blocks, the body of your function is treated as the <code>end</code> block. This is so that you can use the special <code>$Input</code> variable, which collects all the things passed in on the pipeline, and thus only works in the <code>end</code> block.  That would allow the following function to behave the same way regardless of whether it was invoked on the pipeline or by passing an <code>$InputObject</code>. Notice, however, the difference between this, and the function above.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666699; font-weight: bold;">Function</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquareEnd</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666699; font-weight: bold;">PARAM</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$label</span>, <span style="color: #660033; font-weight: bold;">$color</span><span style="color: #66cc66;">=</span><span style="color: #009900;">&quot;White&quot;</span>, <span style="color: #660033; font-weight: bold;">$InputObject</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">BEGIN</span> &nbsp; <span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Begin $Label&quot;</span> <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">PROCESS</span> <span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;$Label <span style="color: #000099; font-weight: bold;">`t</span> $_&quot;</span> <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">END</span> &nbsp; &nbsp; <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">## because one of $Input or $InputObject must be null:</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">Foreach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$item</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$Input</span> <span style="color: #66cc66;">+</span> <span style="color: #660033; font-weight: bold;">$InputObject</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;$Label <span style="color: #000099; font-weight: bold;">`t</span> $item&quot;</span> <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$item</span> <span style="color: #66cc66;">*</span> <span style="color: #660033; font-weight: bold;">$item</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># and test it like this</span><br />
1..5 <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquareEnd</span></span> one cyan <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquareEnd</span></span> two yellow <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquareEnd</span></span> three green<br />
<br />
<span style="color: #666666; font-style: italic;"># Or like this</span><br />
1..5 <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquarePipe</span></span> one cyan <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquareEnd</span></span> two yellow <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">SquareEnd</span></span> three green<br />
&nbsp;</div>

	<h3>Our challenge </h3>

	<p>The basic idea here is to rewrite that function such that it can be used to process a set of numbers from <em>either</em> the pipeline or an argument, without interfering with the processing of other parameters. We require that the function process items as they come in, rather than waiting until it&#8217;s received all input before processing them the way <code>Test-SquareEnd</code> does.</p>

	<h4>In PowerShell 2.0 this would be easy </h4>

	<p>In the current <span class="caps">CTP</span> 3 of PowerShell 2, you just specify <code>ValueFromPipeline=$true</code> for the parameter you want to set from the pipeline, and the function will work the same way whether you pass the numbers as a parameter or along the pipeline &#8212; you can even control which attribute of the objects on the pipeline will be used, but that&#8217;s <a href="a-guide-to-advanced-functions">a whole other article</a>.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666699; font-weight: bold;">Function</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666699; font-weight: bold;">PARAM</span><span style="color: #333;">&#40;</span> <br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$label</span><br />
, &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>ConsoleColor<span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$color</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;White&quot;</span><br />
, &nbsp;<span style="color: #333;">&#91;</span>Parameter<span style="color: #333;">&#40;</span>ValueFromPipeline<span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$true</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span><br />
&nbsp; &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">Int</span><span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$InputObject</span> <br />
<span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">BEGIN</span> &nbsp; <span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Begin $Label&quot;</span> <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">END</span> &nbsp; &nbsp; <span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;End $Label&quot;</span> &nbsp; <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">PROCESS</span> <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">ForEach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$i</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$InputObject</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;$Label $i&quot;</span> <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$i</span> <span style="color: #66cc66;">*</span> <span style="color: #660033; font-weight: bold;">$i</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## Either way we call these, they have the same output</span><br />
<span style="color: #666666; font-style: italic;">## Unlike what Get-SquarePipe or Get-SquareEnd </span><br />
<span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">3</span>,<span style="color: #cc66cc;">4</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> one green <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> two cyan<br />
<span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> one green <span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">3</span>,<span style="color: #cc66cc;">4</span> &nbsp; <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> two cyan<br />
&nbsp;</div>

	<p>Of course, PowerShell 2.0 is still in beta status, and even after it&#8217;s released you may need to write scripts that are backwards compatible to PowerShell 1.0, and the excercise of doing so may  help you to understand more about how PowerShell functions work, and particularly how they behave in the pipeline.</p>

	<h3>Our solution</h3>

	<p>Since in a PowerShell 1.0 function it&#8217;s not really supported directly, we need to do some extra work:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">PARAM</span><span style="color: #333;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$label</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;&quot;</span><br />
&nbsp; &nbsp;, &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>ConsoleColor<span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$color</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;White&quot;</span><br />
&nbsp; &nbsp;, &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">Int</span><span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$InputObject</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$null</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#41;</span> <br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">BEGIN</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$InputObject</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## If you accepted additional params, you'd need to pass those in</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Output</span></span> <span style="color: #660033; font-weight: bold;">$InputObject</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">&amp;</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$MyInvocation</span>.<span style="color: #003366;">InvocationName</span><span style="color: #333;">&#41;</span> <span style="color: #000066;">-Label</span> <span style="color: #660033; font-weight: bold;">$label</span> <span style="color: #000066;">-Color</span> <span style="color: #660033; font-weight: bold;">$color</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## break</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Begin $Label&quot;</span> <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">PROCESS</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">## If you specify a type for $InputObject, test for that here</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$_</span> <span style="color: #000066;">-is</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">Int</span><span style="color: #333;">&#93;</span></span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;$Label $_&quot;</span> <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$_</span> <span style="color: #66cc66;">*</span> <span style="color: #660033; font-weight: bold;">$_</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">elseif</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$_</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">throw</span> <span style="color: #009900;">&quot;$_ is not a System.Int32&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">END</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #66cc66;">!</span><span style="color: #660033; font-weight: bold;">$InputObject</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;End $Label&quot;</span> &nbsp; <span style="color: #000066;">-Foreground</span> <span style="color: #660033; font-weight: bold;">$color</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
&nbsp;</div>

	<h3>An explanation</h3>

	<p>Of course, this is just an example method, squaring things isn&#8217;t that exciting &#8212; but what&#8217;s special about it is that the output is almost exactly the same whether you call it with parameters <code>Get-Square 1,2,3,4</code> or on the pipeline: <code>1,2,3,4 | Get-Square</code>.    </p>

	<p>The trick is that it actually executes the same way in either case:</p>

	<ol>
		<li>If you call it by passing the int (or array of ints) as an argument (<code>$InputObject</code>), it calls itself and passes those values on the pipeline.</li>
		<li>When the integers are passed on the pipeline, the special pipeline iterator variable <code>$_</code> is set, and the process block is executed.</li>
	</ol>
	<ol>
		<li>When it has to (re)invoke itself, it passes any other parameters as parameters, which means you need to have default values for them.</li>
	</ol>

	<p>There is <em>one</em> tiny difference in the processing, which in real-world use is practically never noticeable (you can see it in our example if you call it like this): </p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> one green <span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">3</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> two cyan<br />
<span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">3</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> one green <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Square</span></span> two cyan<br />
&nbsp;</div>

	<p>You&#8217;ll see that unlike the PowerShell 2.0 pipeline function, when you pass the numbers as a parameter, the first one of them actually gets passed through the <code>process</code> block before the <code>begin</code> block of the second function on the pipeline is called. This usually doesn&#8217;t have any effect, but it&#8217;s something to keep in the back of your head.</p>

	<h3>A few precautions: </h3>

	<ul>
		<li>You have to default values for parameters, because you&#8217;ll be passing them all as named parameters, in the re-invoke step, and <code>$null</code> can cause problems.</li>
		<li>If you need to do additional processing in the <code>begin</code> block, you should only do so in an <code>ELSE</code> case: when $InputObject is null.  That way, the code will only execute <em>once</em> each time you call the function. </li>
		<li>The same goes for the <code>end</code> block: you have to keep your code in an <code>If(!$InputObject)</code> block to avoid executing it twice (when you pass the values as an argument, and it re-invokes itself). </li>
	</ul>
	<ul>
		<li>The test cases in the <code>process</code> block <em>must</em> wrap all of your process block code, so that you don&#8217;t process the arguments twice, and you shouldn&#8217;t refer to $InputObject, but instead should use the automatic <code>$_</code> variable which is the value passed when the function is (re)invoked via the pipeline.</li>
	</ul>

	<p>Here&#8217;s some sample output, in case you&#8217;re wondering:</p>

	<div class="text code text" style="font-family:monospace;"><br />
PS&gt; Get-Square test cyan 2,3,4<br />
Begin test<br />
test 2<br />
4<br />
test 3<br />
9<br />
test 4<br />
16<br />
End test<br />
<br />
PS&gt; 2,3,4|Get-Square test cyan<br />
Begin test<br />
test 2<br />
4<br />
test 3<br />
9<br />
test 4<br />
16<br />
End test<br />
&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/using-script-functions-in-the-powershell-pipeline-take-two/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ideas for Writing Composable PowerShell scripts</title>
		<link>http://huddledmasses.org/ideas-for-writing-composable-powershell-scripts/</link>
		<comments>http://huddledmasses.org/ideas-for-writing-composable-powershell-scripts/#comments</comments>
		<pubDate>Wed, 28 May 2008 13:33:07 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PowerTips]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/ideas-for-writing-composable-powershell-scripts/</guid>
		<description><![CDATA[I was just having some fun with some recent blog posts&#8230; WPF &#38; PowerShell &#8211; Part 5 has a script for &#8220;Get-Listbox&#8221; and for &#8220;Show-Control&#8221; and Halr9000 wrote a script he called Get-PSBlogroll I had modified the example from the WPF post to create a listbox which will &#8220;start&#8221; whatever you double click &#8230; Get-Listbox [...]]]></description>
			<content:encoded><![CDATA[	<p>I was just having some fun with some recent blog posts&#8230;</p>

	<p><a href="http://blogs.msdn.com/powershell/archive/2008/05/26/wpf-powershell-part-5-using-wpf-powershell-modules.aspx"><span class="caps">WPF</span> &amp; PowerShell &#8211; Part 5</a> has a script for &#8220;Get-Listbox&#8221; and for &#8220;Show-Control&#8221; and Halr9000 wrote a script he called <a href="http://halr9000.com/article/487">Get-PSBlogroll</a> </p>

	<p>I had modified the example from the <span class="caps">WPF</span> post to create a listbox which will &#8220;start&#8221; whatever you double click &#8230;</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Listbox</span></span> Title <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Show-<span style="font-style: normal;">Control</span></span> @<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&quot;MouseDoubleClick&quot;</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Diagnostics.<span style="color: #666699; font-weight: bold;">Process</span><span style="color: #333;">&#93;</span></span>::<span style="color: #660033;">Start</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">Content</span>.<span style="color: #003366;">SelectedItem</span> <span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span></div>

	<p>And I tried something like this to let me launch links from hal9000&#8217;s blogroll:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">PsBlogRoll</span></span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">HtmlUrl</span> <span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Listbox</span></span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Show-<span style="font-style: normal;">Control</span></span> @<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&quot;MouseDoubleClick&quot;</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Diagnostics.<span style="color: #666699; font-weight: bold;">Process</span><span style="color: #333;">&#93;</span></span>::<span style="color: #660033;">Start</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">Content</span>.<span style="color: #003366;">SelectedItem</span> <span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span></div>

	<p>Of course, what I&#8217;d like is to <em>see</em> the titles, instead of the <span class="caps">URL</span>, but because of how Get-ListBox was written, it only accepts strings, and therefore only returns strings.  I tried adding the <span class="caps">URL</span> as a NoteProperty on the title string, but there&#8217;s <a href="https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=345387&#38;amp;SiteID=99">a bug</a> in the script cmdlet implementation that strips <acronym title="Extended Type System">ETS</acronym> properties. So if you specify your parameter type as a [string], you loose the NoteProperty.</p>

	<h2>Idea 1: Use [PsObject] for your pipeline parameter</h2>

	<p>Of course, if they <a href="https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=345387&#38;amp;SiteID=99">fix the bug</a> this tip will go away, but in the meantime, you&#8217;re better off not casting the input from the PowerShell native <code>[PsObject]</code> type, because you loose any extended type system attributes (and if you cast <span class="caps">XML</span> to a string, it comes out yucky).</p>

	<h2>Idea 2: Don&#8217;t output xml nodes</h2>

	<p>Even after fixing the Get-Listbox script so it outputs what it gets in without casting it, I still have to craft PsObjects with the output from Halr9000&#8217;s script, because otherwise Get-ListBox just outputs the <code>.ToString()</code> representation of the xml node, which is invariably useless &#8212; I could data-bind to the xml attributes, but it requires a separate syntax in the <span class="caps">XAML</span> &#8212; which means you&#8217;d have to have separate code for xml vs objects.  So basically, you&#8217;re better off with a <code> | Select *</code> at the end of your Get-PsBlogRoll.</p>

	<h2>Idea 3: Display scripts should take a property (or a property list)...</h2>

	<p>What I eventually ended up doing is rewriting Get-Listbox to take a &#8220;Properties&#8221; parameter so that I could specify which of the attributes of an object I wanted to use &#8230; that way, I can pass in the almost unmodified output from Get-PSBlogRoll into the new Get-ListBox, and run with it.  In the end, it looks something like this:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
cmdlet <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Listbox</span></span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">param</span><span style="color: #333;">&#40;</span> &nbsp; <br />
&nbsp; &nbsp; <span style="color: #333;">&#91;</span>Parameter<span style="color: #333;">&#40;</span>ValueFromPipeline<span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$true</span>, Mandatory<span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$true</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span><span style="color: #660033; font-weight: bold;">$Input</span>,<br />
&nbsp; &nbsp; <span style="color: #333;">&#91;</span>Parameter<span style="color: #333;">&#40;</span>Position<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">0</span>,Mandatory<span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$false</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Properties</span><br />
&nbsp; &nbsp; <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">Begin</span><span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$listItems</span> <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">Process</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$input</span> <span style="color: #000066;">-is</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">type</span><span style="color: #333;">&#93;</span></span> <span style="color: #000066;">-and</span> <span style="color: #660033; font-weight: bold;">$input</span>.<span style="color: #003366;">IsEnum</span> <span style="color: #333;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$listItems</span><span style="color: #66cc66;">+=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Enum<span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">GetValues</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$input</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">elseif</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$input</span>.<span style="color: #003366;">GetType</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span>.<span style="color: #003366;">IsEnum</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$listItems</span><span style="color: #66cc66;">+=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Enum<span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">GetValues</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$input</span>.<span style="color: #003366;">GetType</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">else</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$listItems</span> <span style="color: #66cc66;">+=</span> <span style="color: #660033; font-weight: bold;">$input</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">End</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$listbox</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Windows</span>.<span style="color: #003366;">Controls</span>.<span style="color: #003366;">Listbox</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$listBox</span>.<span style="color: #003366;">ItemsSource</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$listItems</span> <span style="color: #666666; font-style: italic;"># | Select -unique</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># An optional DataTemplate, if they specified which properties they want to see</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Properties</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$xml</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;&lt;DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'&gt;&lt;StackPanel&gt;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$property</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$Properties</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$xml</span> <span style="color: #66cc66;">+=</span> <span style="color: #009900;">&quot;&lt;TextBlock Text='{Binding Path=$($property)}'/&gt;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">XML</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$xml</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$xml</span> <span style="color: #66cc66;">+</span> <span style="color: #009900;">&quot;&lt;/StackPanel&gt;&lt;/DataTemplate&gt;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$listBox</span>.<span style="color: #003366;">ItemTemplate</span> <span style="color: #66cc66;">=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Windows.<span style="color: #003366;">Markup</span>.<span style="color: #003366;">XamlReader</span><span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">Load</span><span style="color: #333;">&#40;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366; font-weight: bold;">Xml</span>.<span style="color: #003366;">XmlNodeReader</span> <span style="color: #660033; font-weight: bold;">$xml</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$listBox</span><br />
&nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">PsBlogRoll</span></span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$webClient</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> System.<span style="color: #003366;">Net</span>.<span style="color: #003366;">WebClient</span><br />
&nbsp; &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">xml</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Opml</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$webClient</span>.<span style="color: #003366;">DownloadString</span><span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;http://bloglines.com/export?id=halr9000&quot;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$PsBlogroll</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$Opml</span>.<span style="color: #003366;">opml</span>.<span style="color: #003366;">body</span>.<span style="color: #003366;">outline</span> <span style="color: #66cc66;">|</span> Where<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">text</span> <span style="color: #000066;">-eq</span> <span style="color: #009900;">'@Powershell'</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## The Select statement outputs a custom PSObject instead of the original (XmlNode) object</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$PsBlogroll</span>.<span style="color: #003366;">Outline</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Select-<span style="font-style: normal;">Object</span></span> title, text, htmlUrl, xmlUrl<br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">PSBlogRoll</span></span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Listbox</span></span> title <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Show-<span style="font-style: normal;">Control</span></span> @<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&quot;MouseDoubleClick&quot;</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># But now I can use the &quot;HtmlUrl&quot; property to launch it in my browser</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Diagnostics.<span style="color: #666699; font-weight: bold;">Process</span><span style="color: #333;">&#93;</span></span>::<span style="color: #660033;">Start</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$window</span>.<span style="color: #003366;">Content</span>.<span style="color: #003366;">SelectedItem</span>.<span style="color: #003366;">HtmlUrl</span> <span style="color: #333;">&#41;</span> <br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span></div>

	<p>Of course, because of how I wrote the DataTemplate for the properties (using a StackPanel and a loop to output multiple TextBlock objects) you could choose to show the Url as well, and all you&#8217;d have to do is change the call to Get-Listbox like this: <code>Get-Listbox title,htmlUrl</code> &#8230; which is pretty cool.  Does anyone else have any ideas for making these even easier to compose?  </p>

	<p>A <em>really</em> nice trick would be if the wpf cmdlet could use <code>Write-Output</code> in the click handler and actually <code>yield</code> to allow the rest of the pipeline to process that item, but so far, I haven&#8217;t been able to find a way to do that (short of closing the <span class="caps">WPF</span> window, of course).</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/ideas-for-writing-composable-powershell-scripts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Pipeline Input vs Parameters in PowerShell scripts</title>
		<link>http://huddledmasses.org/pipeline-input-vs-parameters-in-powershell-scripts/</link>
		<comments>http://huddledmasses.org/pipeline-input-vs-parameters-in-powershell-scripts/#comments</comments>
		<pubDate>Fri, 25 Apr 2008 06:20:07 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PowerShell Functions]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/pipeline-input-vs-parameters-in-powershell-scripts-2/</guid>
		<description><![CDATA[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&#8217;d share it with you all in case it helps clear things up for you. We&#8217;ll call him &#8220;user&#8221; since he left before I could [...]]]></description>
			<content:encoded><![CDATA[	<p>A relatively new PowerShell user came into #PowerShell on <span class="caps">IRC</span>.FreeNode.net this week to ask a question about scripts and the pipeline, and the conversation went so well, that I thought I&#8217;d share it with you all in case it helps clear things up for you.  We&#8217;ll call him &#8220;user&#8221; since he left before I could get his permission to paste this, and I&#8217;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.</p>

	<p><b style="width:5em; display: block; float: left;">user:</b> Can you explain the distinction between $_ and a param in a script context?<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> I sure can. And I think I can do it simply &#8230; take an example script|function &#8230; actually, we&#8217;ll just use a scriptblock<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> it can have pipeline blocks, or not (the pipeline blocks are the BEGIN{...} PROCESS{...} END{...})<br />
<b style="width:5em; display: block; float: left;">user:</b> yeah, I&#8217;m with you<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> so if you pass a value via an argument, it&#8217;s present in all three blocks, and has the same value the whole time (unless you change it in your script)<br />
<b style="width:5em; display: block; padding: 0px; float: left;">user:</b> <em>really</em><br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> But when you put that script in a pipeline, your <span class="caps">BEGIN</span> {} block is called first, and then for <span class="caps">EACH</span> item in the pipeline, powershell sets $_ and calls your <span class="caps">PROCESS</span> block, and finally, your END{} block is called after all pipeline items have been processed<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> Here, check this out (run it so you can see) <span id="more-518"></span></p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #009900;">&quot;one&quot;</span>,<span style="color: #009900;">&quot;two&quot;</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">&amp;</span>amp;amp;<span style="color: #333;">&#123;</span><br />
<span style="color: #666699; font-weight: bold;">BEGIN</span> <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$Arg</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$Args</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Begin $Arg&quot;</span> <span style="color: #000066;">-Fore</span> Green <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Begin (empty) Pipeline: $_&quot;</span> <span style="color: #000066;">-Fore</span> Green<br />
<span style="color: #333;">&#125;</span><br />
<span style="color: #666699; font-weight: bold;">PROCESS</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$Arg</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$Args</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Process $Arg&quot;</span> <span style="color: #000066;">-Fore</span> Cyan <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Process Pipeline: $_&quot;</span> <span style="color: #000066;">-Fore</span> Cyan<br />
<span style="color: #333;">&#125;</span><br />
<span style="color: #666699; font-weight: bold;">END</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$Arg</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$Args</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;End $Arg&quot;</span> <span style="color: #000066;">-Fore</span> yellow <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;End Pipeline: $_&quot;</span> <span style="color: #000066;">-Fore</span> Yellow<br />
<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #009900;">&quot;three&quot;</span>,<span style="color: #009900;">&quot;four&quot;</span> <span style="color: #009900;">&quot;five&quot;</span>,<span style="color: #009900;">&quot;six&quot;</span> <span style="color: #666666; font-style: italic;"># these are parameters to our script</span></div>

	<p><b style="width:5em; display: block; float: left;">user:</b> that really helps, thank you<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> no problem. Incidentally &#8230; in a script-block like that, you <em>can</em> use the Params() statement, but I wanted to loop over $args  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';)' class='wp-smiley' /> <br />
<b style="width:5em; display: block; float: left;">user:</b> based on that I&#8217;m left wondering what the value of parameters is.<br />
<b style="width:5em; display: block; float: left;">user:</b> If I&#8217;m writing a script, chances are that I&#8217;m going to want to use it in a pipeline<br />
<b style="width:5em; display: block; float: left;">user:</b> I guess I can use parameters, but put it in a foreach-object block<br />
<b style="width:5em; display: block; float: left;">user:</b> $arr | %{myscript $_}<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> Well,  if you use the foreach-object block and pass arguments, your script doesn&#8217;t persist through the life of the pipeline, so you can&#8217;t do things like counting, or comparing to the previous object, etc.<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> 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/ )<br />
<b style="width:5em; display: block; float: left;">user:</b> right. So I guess the concept is that scripts grab stuff off the pipeline themselves?<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> sort-of, yeah. I mean, it&#8217;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.</p>

	<p><b style="width:5em; display: block; float: left;">Jaykul:</b> In v2, you can be more explicit about this, because you can write a &#8220;cmdlet&#8221; in script which lets you specify parameters which should get the pipeline value<br />
<b style="width:5em; display: block; float: left;">user:</b> okay, I totally get it now. That&#8217;s why you&#8217;d write a cmdlet instead of a script?<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> Yeah! The particularly cool thing about cmdlet parameter handling &#8230; is you can do this:<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> [Parameter(FromPipelineByPropertyValue)] [Alias(&#8220;FullName&#8221;)] $FileName<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> a parameter like that would accept a string as a parameter, but if you did <code>gci * | scriptcmdlet</code> instead of getting the [System.IO.FileInfo] object you would get the <span class="caps">STRING</span> corresponding to that object&#8217;s FullName property<br />
<b style="width:5em; display: block; float: left;">user:</b> right. sweet!<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> so you can even do tricky stuff like getting multiple properties from it (as different parameters to your script)</p>

	<p><b style="width:5em; display: block; float: left;">user:</b> I noticed from http://powershellcentral.com/scripts/184 that you&#8217;re testing the type of the pipeline object<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> yeah<br />
<b style="width:5em; display: block; float: left;">user:</b> FIleInfo vs. string<br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> because it lets me do this: <code>ls *.ps1 | Send-Paste</code><br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> or this: <code>get-history -count 5 | % { $_.CommandLine } | Send-Paste</code><br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> or even send multiple files as a single paste, like: <code>get-content *.ps1 | Send-Paste</code><br />
<b style="width:5em; display: block; float: left;">Jaykul:</b> (note that in this script, that&#8217;s <span class="caps">VERY</span> different than ls *.ps1 | Send-Paste &#8230;. which would create a paste for each file)<br />
<b style="width:5em; display: block; float: left;">user:</b> wow, this is good stuff, thanks for the time&#8230;</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/pipeline-input-vs-parameters-in-powershell-scripts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reservoir sampling and performance considerations</title>
		<link>http://huddledmasses.org/reservoir-sampling-and-performance-considerations/</link>
		<comments>http://huddledmasses.org/reservoir-sampling-and-performance-considerations/#comments</comments>
		<pubDate>Mon, 21 Jan 2008 04:25:41 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Randomization]]></category>
		<category><![CDATA[Reservoir Sampling]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/reservoir-sampling-and-performance-considerations/</guid>
		<description><![CDATA[I started this post a few weeks ago, but never quite got around to posting it, and then I saw today that Dmitry wrote about the memory problems with using measure-object and I thought this would be a great time to post this. Essentially, this is a continuation of my exploration of development in the [...]]]></description>
			<content:encoded><![CDATA[	<p>I started this post a few weeks ago, but never quite got around to posting it, and then I saw today that <a href="http://dmitrysotnikov.wordpress.com/2008/01/18/measure-vs-count-vs-i/">Dmitry wrote about the memory problems with using measure-object</a> and I thought this would be a great time to post this.  Essentially, this is a continuation of my exploration of development in the PowerShell pipeline, and we&#8217;ll see some of the problems with the way that the pipeline works and what happens if you overlook the numbers of items that could be in the pipeline.</p>

	<p>Dmitry was trying to count the number of users in Active Directory, and ran into ridiculous memory use when using Measure-Object because it appears to collect all the items in the pipeline into memory before it counts, resulting in huge amounts of memory use based on the number of objects you&#8217;re counting.  Of course, for the purpose of counting, it&#8217;s a pretty obvious fix (as Dmitry explains), but for other purposes it may not be as obvious.</p>

	<h3>Select Random</h3>

	<p>When I originally started this post, I was trying to upgrade my original <a href="http://powershellcentral.com/scripts/60">Select-Random</a> script (which was published in the PowerShell Community Extensions) to use reservoir sampling in an attempt to solve the same problem.  Select-Random is a script which selects a random element from a collection or from the pipeline. In the past, if the elements were passed in as an argument, it simply collected them into an array (in a really inefficient way, but never mind) and then picks a random number and selects the item by index.</p>

	<p>I started by improving the collection method to use an ArrayList and reduced the memory usage to about 1/5th of the original method, and then rewrote the whole script to use reservoir sampling instead. <a href="http://gregable.com/2007/10/reservoir-sampling.html">Greg wrote a good explanation of reservoir sampling</a> but basically it&#8217;s an algorithm for choosing random items from a collection of unknown size without having to traverse the collection twice (to count it the first time and then to select) &#8212; in my case, the need to count the collection was requiring me to store the pipeline input in an array, so the improvement was more about memory use than about needing to enumerate the list twice. However, there <strong>is</strong> a downside: it&#8217;s slower.  <span id="more-483"></span></p>

	<h3>Reservoir Sampling</h3>

	<p>Reservoir sampling means that instead of generating a single random number and indexing into the collection, you sample as you iterate. You start by filling your &#8220;reservoir&#8221; with the first items in the pipeline, and then for each item remaining in the pipeline, you generate a random number with a decreasing probability of choosing the item. You&#8217;re trading memory usage for speed. Basically, if you want $count items, then the script stores $count elements (the eventual result) at all times. It continues processing elements until it reaches the end of the input. </p>

	<ul>
		<li>For each input element $n (where n is the count of the inputs so far) there is a $count/$n chance that it becomes part of the result.</li>
		<li>For each previously selected element, there is a $count/($n-1) chance of it remaining selected (ie: not being replaced).</li>
	</ul>
	<ul>
		<li>For the ones selected, there&#8217;s a ($count/$n * 1/$count = 1/$n) chance of it being replaced, so a ($n-1)/$n chance of it remaining &#8230; thus, it&#8217;s cumulative probability of being among the selected elements after the nth input is processed is $count/($n-1) * ($n-1)/$n = $count/$n, as it should be.</li>
	</ul>

	<p>The bottom line is that using this method is a <span class="caps">LOT</span> slower than random indexing. However, it uses a <span class="caps">LOT</span> less memory when iterating large numbers of items that are output by cmdlets as long as they weren&#8217;t already collected into an array. As a simple example, Get-ChildItem outputs each item as it traverses the provider, rather than creating an in-memory collection. If nothing in the pipeline &#8220;collects&#8221; all of the output, then it never needs to use memory except for the text display of them &#8230; or if it&#8217;s piped through a reservoir sampling algorithm, it only uses the amount of memory required to store as many items as the size of our sample.</p>

	<h3>Performance comparison</h3>

	<p>Using as an example the output of Get-ChildItem -Recurse on my profile directory, where there are about 98 thousand items total in the subdirectories, I ran each test in it&#8217;s own clean console so that I could see the results of the memory usage cleanly.  So that you could tell the difference, I changed the letters in the prompt for each test (I also use a counter in my prompt, and I change the character from > to : to make my life easier when pasting into <span class="caps">HTML</span>).  </p>

	<p>In case you&#8217;re not familiar with the commands used here, Measure-Command is a cmdlet that times how long a script takes to run, and if you wrap it in a string, it outputs a simple elapsed time statement, instead of more verbose output.  There are other ways of accomplishing the same thing, but this is the least distracting way. Also, -f is the format operator, so putting <code>&#34;{0}&#34; -f 42</code> is the same as @[string]::format(&#8221;{0}&#8221;,42) but in less<br />
code.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>A1<span style="color: #333;">&#93;</span></span>: <span style="color: #666666; font-style: italic;"># Collect the items first, and pass them as a parameter to Select-Random</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>A2<span style="color: #333;">&#93;</span></span>: <span style="color: #009900;">&quot;$(measure-command {Select-Random -count 5 -input (ls -recurse)})&quot;</span><br />
00:00:<span style="color: #cc66cc;">32.8902287</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>A3<span style="color: #333;">&#93;</span></span>: <span style="color: #009900;">&quot;{0:#,#}&quot;</span> <span style="color: #000066;">-f</span> <span style="color: #333;">&#40;</span><span style="color: #333;">&#40;</span><span style="color: #660033;">ps</span> <span style="color: #003366; font-weight: bold;">powershell</span><span style="color: #66cc66;">*</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #333;">&#93;</span>.<span style="color: #003366;">WorkingSet</span><span style="color: #66cc66;">/</span>1KB<span style="color: #333;">&#41;</span><br />
<span style="color: #cc66cc;">189</span>,<span style="color: #cc66cc;">624</span><br />
<br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>B1<span style="color: #333;">&#93;</span></span>: <span style="color: #666666; font-style: italic;"># Pass the items via the pipeline, but use the -collect method</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>B2<span style="color: #333;">&#93;</span></span>: <span style="color: #009900;">&quot;$(measure-command {ls -recurse | Select-Random -count 5 -collect})&quot;</span><br />
00:00:<span style="color: #cc66cc;">40.6224274</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>B3<span style="color: #333;">&#93;</span></span>: <span style="color: #009900;">&quot;{0:#,#}&quot;</span> <span style="color: #000066;">-f</span> <span style="color: #333;">&#40;</span><span style="color: #333;">&#40;</span><span style="color: #660033;">ps</span> <span style="color: #003366; font-weight: bold;">powershell</span><span style="color: #66cc66;">*</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #333;">&#93;</span>.<span style="color: #003366;">WorkingSet</span><span style="color: #66cc66;">/</span>1KB<span style="color: #333;">&#41;</span><br />
<span style="color: #cc66cc;">73</span>,<span style="color: #cc66cc;">688</span> <br />
<br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>C1<span style="color: #333;">&#93;</span></span>: <span style="color: #666666; font-style: italic;"># Pass the items on the pipeline and use reservoir sampling</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>C2<span style="color: #333;">&#93;</span></span>: <span style="color: #009900;">&quot;$(measure-command {ls -recurse | Select-Random -count 5})&quot;</span><br />
00:00:<span style="color: #cc66cc;">52.7225395</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>C3<span style="color: #333;">&#93;</span></span>: <span style="color: #009900;">&quot;{0:#,#}&quot;</span> <span style="color: #000066;">-f</span> <span style="color: #333;">&#40;</span><span style="color: #333;">&#40;</span><span style="color: #660033;">ps</span> <span style="color: #003366; font-weight: bold;">powershell</span><span style="color: #66cc66;">*</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #333;">&#93;</span>.<span style="color: #003366;">WorkingSet</span><span style="color: #66cc66;">/</span>1KB<span style="color: #333;">&#41;</span><br />
<span style="color: #cc66cc;">43</span>,<span style="color: #cc66cc;">188</span></div>

	<p>Hopefully I didn&#8217;t make that example too complicated, and you can see not only that collecting the output into an array is faster, but that is uses a boatload more memory.  You can also see that my -collect method (which now uses an ArrayList (see the code below)) uses a lot less memory than collecting the items in an array the way the first example does.  I&#8217;m not 100% sure why this is, but my theory is that doing (ls -recurse) is in effect the same as using the += operator on an array &#8212; it makes a copy. To be more precise, it makes about 98 thousand copies.</p>

	<p>You&#8217;re not getting quite the whole picture in that example, but to fill it in a little: the memory use starts at around 39 MB &#8230; <span class="caps">JUST</span> doing the Get-ChildItem to count the files increases the working set memory usage of the PowerShell process by about 3.5 MB. Using the reservoir method to select 5 of them increased the memory usage of the PowerShell process by about 5 MB of memory (only 2 MB more than simple counting).  Using the pre-collection method requires around 151 MB. That&#8217;s a really heavy price to pay in memory, at over 1.5 KB per item in the collection.  And even the -collect method uses almost 10x as much memory.</p>

	<h3>Some perspective</h3>

	<p>To make sure you have a chance to get the same perspective I have on this &#8230; let me show you the output another way. The key thing to see in these last two examples is that the memory cost is the same for both &#8212; the same 151MB of the earlier collection example. The difference in time is large and undeniable. If you compare this with example A, you can see that basically, listing the files takes 32 seconds, and picking 25 of them takes about a tenth of a second, while iterating them (which requires generating about 98 thousand random numbers) takes about 20 seconds.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>D1<span style="color: #333;">&#93;</span></span>: <span style="color: #660033; font-weight: bold;">$files</span> <span style="color: #66cc66;">=</span> <span style="color: #660033;">ls</span> <span style="color: #000066;">-recurse</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>D2<span style="color: #333;">&#93;</span></span>: <span style="color: #009900;">&quot;$(measure-command {Select-Random -Count 25 -input $files})&quot;</span><br />
00:00:<span style="color: #cc66cc;">00.1337390</span><br />
<br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>E1<span style="color: #333;">&#93;</span></span>: <span style="color: #660033; font-weight: bold;">$files</span> <span style="color: #66cc66;">=</span> <span style="color: #660033;">ls</span> <span style="color: #000066;">-recurse</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>E2<span style="color: #333;">&#93;</span></span>: <span style="color: #009900;">&quot;$(measure-command {$files | Select-Random -Count 25})&quot;</span><br />
VERBOSE: Selected <span style="color: #cc66cc;">2</span> of <span style="color: #cc66cc;">97849</span> elements<br />
00:00:<span style="color: #cc66cc;">19.9349478</span></div>

	<h3>Conclusion</h3>

	<p>So, the point is: there are times when you need to sacrifice speed in order to keep your memory usage low &#8230; But when you&#8217;re writing a general-purpose script or a cmdlet for the PowerShell pipeline, you need to at least understand the choice you&#8217;re making so you can make it deliberately. Sometimes you&#8217;ll choose to write it fast and memory-expensive.  Sometimes you&#8217;ll choose to write it slower and memory-lean.  And sometimes, like I did here, you might choose to do both  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';)' class='wp-smiley' /> .</p>

	<h5>The script &#8230; </h5>

	<p>It&#8217;s also <a href="http://powershellcentral.com/scripts/118">script 118</a> on the <a href="http://powershellcentral.com/scripts/">PowerShell central script repository</a>  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' />  (where it has a comment header that&#8217;s giving me problems here).</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666699; font-weight: bold;">param</span><span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">int</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$count</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$collectionMethod</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">array</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$inputObject</span><span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$null</span><span style="color: #333;">&#41;</span> <br />
<br />
<span style="color: #666699; font-weight: bold;">BEGIN</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$args</span> <span style="color: #000066;">-eq</span> <span style="color: #009900;">'-?'</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
@<span style="color: #009900;">&quot;<br />
Usage: Select-Random [[-Count] &lt;int&gt;] [-inputObject] &lt;array&gt; (from pipeline) [-?]<br />
<br />
Parameters:<br />
&nbsp;-Count &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: The number of elements to select.<br />
&nbsp;-inputObject &nbsp; &nbsp; &nbsp;: The collection from which to select a random element.<br />
&nbsp;-collectionMethod : Collect the pipeline input instead of using reservoir<br />
&nbsp;-? &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Display this usage information and exit<br />
<br />
Examples:<br />
&nbsp;PS&gt; $arr = 1..5; Select-Random $arr<br />
&nbsp;PS&gt; 1..10 | Select-Random -Count 2<br />
<br />
&quot;</span>@<br />
<span style="color: #666699; font-weight: bold;">exit</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span> <br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">else</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$rand</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> Random<br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$inputObject</span><span style="color: #333;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Write-Output $inputObject | &amp;($MyInvocation.InvocationName) -Count $count</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">elseif</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$collectionMethod</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Verbose</span></span> <span style="color: #009900;">&quot;Collecting from the pipeline &quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Collections.<span style="color: #003366;">ArrayList</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$inputObject</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> Collections.<span style="color: #003366;">ArrayList</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">else</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$seen</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$selected</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> object<span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span> <span style="color: #660033; font-weight: bold;">$count</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<span style="color: #666699; font-weight: bold;">PROCESS</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$_</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$collectionMethod</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$inputObject</span>.<span style="color: #003366;">Add</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$_</span><span style="color: #333;">&#41;</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">out-<span style="font-style: normal;">null</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$seen</span><span style="color: #66cc66;">++</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$seen</span> <span style="color: #000066;">-lt</span> <span style="color: #660033; font-weight: bold;">$count</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$selected</span><span style="color: #333;">&#91;</span><span style="color: #660033; font-weight: bold;">$seen</span><span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #333;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$_</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#125;</span> <span style="color: #666666; font-style: italic;">## For each input element $n there is a $count/$n chance that it becomes part of the result.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">elseif</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$rand</span>.<span style="color: #003366;">NextDouble</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #000066;">-lt</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$count</span><span style="color: #66cc66;">/</span><span style="color: #660033; font-weight: bold;">$seen</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">## For the ones previously selected, there's a 1/$n chance of it being replaced</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$selected</span><span style="color: #333;">&#91;</span><span style="color: #660033; font-weight: bold;">$rand</span>.<span style="color: #003366;">Next</span><span style="color: #333;">&#40;</span><span style="color: #cc66cc;">0</span>,<span style="color: #660033; font-weight: bold;">$count</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$_</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<span style="color: #666699; font-weight: bold;">END</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #66cc66;">-</span><span style="color: #333399; font-weight: bold; font-style: italic;">not</span> <span style="color: #660033; font-weight: bold;">$inputObject</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span> &nbsp;<span style="color: #666666; font-style: italic;">## DO ONCE: (only on the re-invoke, not when using -inputObject)</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Verbose</span></span> <span style="color: #009900;">&quot;Selected $count of $seen elements.&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Output</span></span> <span style="color: #660033; font-weight: bold;">$selected</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># foreach($el in $selected) { Write-Output $el }</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span> <br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">else</span> <br />
&nbsp; &nbsp;<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Verbose</span></span> <span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;{0} elements, selecting {1}.&quot;</span> <span style="color: #000066;">-f</span> <span style="color: #660033; font-weight: bold;">$inputObject</span>.<span style="color: #003366;">Count</span>, <span style="color: #660033; font-weight: bold;">$Count</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$i</span> <span style="color: #666699; font-weight: bold;">in</span> 1..<span style="color: #660033; font-weight: bold;">$Count</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Output</span></span> <span style="color: #660033; font-weight: bold;">$inputObject</span><span style="color: #333;">&#91;</span><span style="color: #660033; font-weight: bold;">$rand</span>.<span style="color: #003366;">Next</span><span style="color: #333;">&#40;</span><span style="color: #cc66cc;">0</span>,<span style="color: #660033; font-weight: bold;">$inputObject</span>.<span style="color: #003366;">Count</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> &nbsp; <br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/reservoir-sampling-and-performance-considerations/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>What&#8217;s the desired behavior of inputObject?</title>
		<link>http://huddledmasses.org/whats-the-desired-behavior-of-inputobject/</link>
		<comments>http://huddledmasses.org/whats-the-desired-behavior-of-inputobject/#comments</comments>
		<pubDate>Sat, 22 Dec 2007 22:59:00 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Behavior]]></category>
		<category><![CDATA[Bugs]]></category>
		<category><![CDATA[Cmdlet]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Documentation]]></category>
		<category><![CDATA[Expectations]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Users]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/whats-the-desired-behavior-of-inputobject/</guid>
		<description><![CDATA[In response to Kirk Munro’s comment on my Writing Cmdlets for the PowerShell Pipeline post: You know, I’ve looked at your articles about cmdlets/functions in the pipeline and I feel you’re missing something. The purpose of the InputObject parameter is to pass in a collection as a single object. This is as opposed to using [...]]]></description>
			<content:encoded><![CDATA[	<p>In response to Kirk Munro’s <a href="http://huddledmasses.org/writing-cmdlets-for-the-powershell-pipeline/feed/">comment</a> on my <a href="http://huddledmasses.org/writing-cmdlets-for-the-powershell-pipeline/">Writing Cmdlets for the PowerShell Pipeline</a> post:</p>

	<blockquote>
		<p>You know, I’ve looked at your articles about cmdlets/functions in the pipeline and I feel you’re missing something. The purpose of the InputObject parameter is to pass in a collection as a single object. This is as opposed to using the pipeline where a collection is passed along the pipeline one item at a time. There are cases where you want to pass in a collection as a collection.</p>
	</blockquote>

	<p>Quite simply, I disagree.  The documentation for these parameters says quite clearly that inputObject “Specifies an object or objects to input to the cmdlet.” This clearly means that I should be able to pass multiple objects, <strong>and have them treated as multiple objects</strong>, not as a single array object.</p>

	<blockquote>
		<p>If you look at your example (Select -First 3 -Unique -InputObject $a), this does in fact work. It receives one object, an array. It then selects the first 3 objects, but there is only 1 so that is moot. And lastly it selects unique objects, but again there is only 1 so that is moot as well and finally the object is output using the default formatter. In this case the default formatter is showing the contents of the array.</p>
	</blockquote>

	<p>In this example, <code>Select-Object</code> has no reason to take a <strong>single object</strong> as an input object, at all.  The only time that it would be useful for Select-Object to take a single inputObject would be in combination with the <code>property</code> parameters. In fact, if you want to Select-Object from an array to get the first of last n objects, or to get a set of unique objects, you <em>have to pass the objects in via the pipeline</em> &#8212; there&#8217;s no other way to make it select from an array. If that was indeed the intent, it should have been written as a <strong>separate ParameterSet</strong>, and <em>the documentation should be changed</em> to reflect that only a single object can be passed in, and that you can&#8217;t use the inputObject parameter with the <code>first</code>, <code>last</code>, or <code>unique</code> parameters at all. That’s worse than useless, it’s misleading and confusing.</p>

	<p>Kirk is absolutely right that if you assume that the InputObject argument is only allowed to take a single object, then the behavior is correct – but it’s not logical.  In fact, the behavior you see in the output of this command is so useless as to be a bug – even if the documentation did not say the parameter accepts multiple objects as input:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #0066cc; font-style: italic;">Select-<span style="font-style: normal;">Object</span></span> <span style="color: #000066;">-input</span> <span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">5</span>,<span style="color: #cc66cc;">6</span>,<span style="color: #cc66cc;">4</span>,<span style="color: #cc66cc;">8</span> <span style="color: #000066;">-first</span> <span style="color: #cc66cc;">2</span> <span style="color: #000066;">-unique</span><br />
<span style="color: #cc66cc;">4</span><br />
<span style="color: #cc66cc;">5</span><br />
<span style="color: #cc66cc;">6</span><br />
<span style="color: #cc66cc;">4</span><br />
<span style="color: #cc66cc;">8</span></div>

	<h3>I know that that’s the way the built-in cmdlets work.</h3>

	<p>But quite frankly, just because someone important wrote something useless is no reason to emulate the behavior.  The inputObject parameter IS the same parameter which pipeline objects go into.  There’s no logical explanation for us to get different results when we pass an array in via the parameter by name instead of via pipeline: the PowerShell pipeline passing the things in the pipeline into the –inputObject parameter … it’s not using some mystical variable like it does in script functions.</p>

	<p>Of course, we all know the powershell pipeline unwraps arrays &#8212; that’s convenient, and we can work around it when we really want to pass an array in:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
PS<span style="color: #66cc66;">&gt;</span> @<span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">int</span><span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#93;</span></span>@<span style="color: #333;">&#40;</span><span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">3</span>,<span style="color: #cc66cc;">4</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span> <span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;Hi: $_&quot;</span> <span style="color: #333;">&#125;</span> <span style="color: #666666; font-style: italic;"># typecast and wrapped isn’t enough...</span><br />
Hi: <span style="color: #cc66cc;">1</span><br />
Hi: <span style="color: #cc66cc;">2</span><br />
Hi: <span style="color: #cc66cc;">3</span><br />
Hi: <span style="color: #cc66cc;">4</span><br />
<br />
PS<span style="color: #66cc66;">&gt;</span> @<span style="color: #333;">&#40;</span>,<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">int</span><span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#93;</span></span>@<span style="color: #333;">&#40;</span><span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">3</span>,<span style="color: #cc66cc;">4</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span> <span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;Hi: $_&quot;</span> <span style="color: #333;">&#125;</span> <span style="color: #666666; font-style: italic;"># put it as a member of another array</span><br />
Hi: <span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">2</span> <span style="color: #cc66cc;">3</span> <span style="color: #cc66cc;">4</span><br />
<br />
PS<span style="color: #66cc66;">&gt;</span> @<span style="color: #333;">&#40;</span>,@<span style="color: #333;">&#40;</span>,<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">int</span><span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#93;</span></span>@<span style="color: #333;">&#40;</span><span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">2</span>,<span style="color: #cc66cc;">3</span>,<span style="color: #cc66cc;">4</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span> <span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;Hi: $_&quot;</span> <span style="color: #333;">&#125;</span> &nbsp;<span style="color: #666666; font-style: italic;"># go too deep and “stuff” happens.</span><br />
Hi: System.<span style="color: #003366;">Int32</span><span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span></div>

	<blockquote>
		<p>My point in all of this is that InputObject is actually a very useful parameter, because there are cases where you really want to pass a collection as a collection into a cmdlet and then do something with it. By making InputObject instead split the collection passed in and pipeline it through, you’re forcing users to wrap collections in an array just to get them passed in as a collection, and personally I don’t feel they should have to do that.</p>
	</blockquote>

	<p>While it’s true that passing in an array is sometimes desirable that’s <strong>not</strong> the reason the parameter exists, and I don’t believe it should be the default behavior here. It should be just as easy for me to use the cmdlet with the inputObject parameter directly as it is to input them via the pipeline.  If I put in unwrapping for the inputObject parameter, you can work around it in the same way I did in the examples above. Incidentally, I think <em>*PowerShell* should unwrap arrays to <strong>ValueFromPipeline</strong> parameters regardless of whether they’re on the pipeline</em>, but I recognize it’s probably too late for that.</p>

	<p>Basically, this is my argument: If inputObject unwraps arrays, the syntax for passing an array by wrapping it in @(,$array) is simple, for those <em>rare</em> occasions when that’s actually what you want. But if it does not unwrap arrays, you’re <strong>forced</strong> to call it via a separate pipeline, because unwrapping the array and passing it in one at a time in a foreach loop will almost certainly not do the same thing, and this is much uglier &#8212; and not compatible with use within the pipeline, particularly if you need to pass the pipeline output into a different parameter.</p>

	<p>I guess my final word would be to agree with Kirk that “InputObject … isn’t documented clearly enough” … in fact, it’s clearly <strong>behaving incorrectly according to the documentation</strong>, and that’s why I originally proposed to unwrap the inputObject parameter when it’s passed as a parameter: to make it work the way the documentation suggests it would,  which seems to me to be a better way than the way it actually works.</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/whats-the-desired-behavior-of-inputobject/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PowerShell 2.0 CTP &#8211; Script Cmdlets</title>
		<link>http://huddledmasses.org/powershell-20-ctp-script-cmdlets/</link>
		<comments>http://huddledmasses.org/powershell-20-ctp-script-cmdlets/#comments</comments>
		<pubDate>Tue, 06 Nov 2007 22:09:57 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Alpha]]></category>
		<category><![CDATA[Beta]]></category>
		<category><![CDATA[Cmdlet]]></category>
		<category><![CDATA[CTP]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/powershell-20-ctp-script-cmdlets/</guid>
		<description><![CDATA[Well, the first alpha CTP release of PowerShell 2.0 is out, and there&#8217;s a lot of new stuff in it &#8230; but I won&#8217;t repeat the list from the PowerShell blog, because I&#8217;m sure you&#8217;ve seen it five or six times already. Instead, lets just skip straight to talking about one of the features we&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[	<p>Well, the first <a href="http://blogs.msdn.com/powershell/archive/2007/11/06/what-s-new-in-ctp-of-powershell-2-0.aspx"><del>alpha</del> <span class="caps">CTP</span> release of PowerShell 2.0</a> is out, and there&#8217;s a lot of new stuff in it &#8230; but I won&#8217;t repeat the list from the PowerShell blog, because I&#8217;m sure you&#8217;ve seen it five or six times already. Instead, lets just skip straight to talking about one of the features we&#8217;ve been hearing about the longest: in PowerShell 2, you can create Cmdlets in script &#8230; bringing nearly full parity between  whats possible in a C# cmdlet and what&#8217;s possible in script.</p>

	<p>There are a few caveats still (Parameter Sets aren&#8217;t working yet, and neither is help, really), and a few surprises &#8230; there&#8217;s a few downsides to PowerShell script vs C# ... but in this particular context one thing that stands out is that in C# the <code>BeginProcessing</code>, <code>ProcessRecord</code>, and <code>EndProcessing</code> blocks are actually methods which can call each other, and as demonstrated in my <a href="/writing-cmdlets-for-the-powershell-pipeline/">tutorial for writing cmdlets that work in the pipeline</a>, they can be recursive &#8212; without getting duplicate variables.  </p>

	<h4>A sample Script Cmdlet</h4>

	<p>In the interests of being the first to publish an interesting script cmdlet  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';)' class='wp-smiley' />  and to continue my recent trend of talking about writing for the PowerShell pipeline, I&#8217;ve merged the logic of my <a href="/writing-better-script-functions-for-the-powershell-pipeline/">script function</a> and my <a href="/writing-cmdlets-for-the-powershell-pipeline/">pipeline cmdlet</a> into a <a href="/wordpress/wp-content/uploads/2007/11/test-pipelinev2.ps1">single sample script cmdlet for PowerShell 2.0</a> and it works great!</p>

	<p>A few observations from the process, in no particular order:</p>

	<ul>
		<li>If you recursively call your cmdlet from within itself, you have to test for parameters using the new <code>$CommandLineParameters.ContainsKey</code> because parameter variables keep their values through recursion if you don&#8217;t explicitly pass a value.</li>
		<li><code>$CommandLineParameters.ContainsKey</code> works differently in the <code>Begin</code> block where it will return <code>$false</code> for arguments which will get their values from the pipeline, than in the <code>Process</code> block where it will treat values which were passed as <code>CommandLineParameters</code> the same as those which were passed via the pipeline.</li>
		<li>If you want to see how your function behaves in a pipeline, you should make sure to test it at different points in the pipeline: at the front, in the middle, and at the end.</li>
		<li>Cmdlets are functions: they show up in the Function provider.</li>
		<li>Cmdlets are functions: they have to be dot-sourced before you can call them.</li>
		<li>Cmdlets are not functions: they are a single command <code>Cmdlet</code> which takes a name (which <strong>must</strong> have a &#8211; in it) and a couple of other parameters followed by a function script block.</li>
	</ul>
	<ul>
		<li>When you recurse by executing &#038;($MyInvocation.InvocationName), that second invocation has an InvocationName of &#8220;&#038;&#8221; ... so you can&#8217;t go any further (this might be a good thing, if you want to stop recursion at one level no matter what. If you want to go further, you need to put your commands into a string, and use <code>Invoke-Expression</code>.</li>
	</ul>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666666; font-style: italic;">#requires -version 2.0</span><br />
<span style="color: #666666; font-style: italic;">###################################################################################################</span><br />
<span style="color: #666666; font-style: italic;">## A Template for Script Cmdlets which can _also_ be executed in the pipeline ....</span><br />
<span style="color: #666666; font-style: italic;">## &nbsp; by Joel Bennett, in hopes it will help...</span><br />
<span style="color: #666666; font-style: italic;">## Version History</span><br />
<span style="color: #666666; font-style: italic;">## v1.0 - First public release (after over 9 different versions in my various other functions)</span><br />
<span style="color: #666666; font-style: italic;">## v1.2 - Show the use of Write-Output, and change &quot;return&quot; in the BEGIN to &quot;Write-Output&quot; to avoid</span><br />
<span style="color: #666666; font-style: italic;">## &nbsp; &nbsp; &nbsp;the pooling of the output from the process block when it's invoked as a function.</span><br />
<span style="color: #666666; font-style: italic;">## v1.3 - Switched back to &quot;break&quot; instead of &quot;return&quot; so that if you pass via the pipeline AND via</span><br />
<span style="color: #666666; font-style: italic;">## &nbsp; &nbsp; &nbsp;the inputObject, only the inputObject gets process (this is how cmdlets behave).</span><br />
<span style="color: #666666; font-style: italic;">## &nbsp; &nbsp; &nbsp;- Cleaned up the comments, and removed the confusing alternate method and $args handling</span><br />
<span style="color: #666666; font-style: italic;">##</span><br />
<span style="color: #666666; font-style: italic;">## v2.0 - First Version as a Script Cmdlet. </span><br />
<span style="color: #666666; font-style: italic;">## &nbsp; &nbsp; &nbsp;This is much easier with support for [ValueFromPipeline] and [ValueFromPipelineByName] </span><br />
<span style="color: #666666; font-style: italic;">##</span><br />
<span style="color: #666666; font-style: italic;">###################################################################################################</span><br />
Cmdlet <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">PipelineV2</span></span> <span style="color: #000066;">-ConfirmImpact</span> low <span style="color: #000066;">-snapin</span> Huddled.<span style="color: #003366;">Tests</span><br />
<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">Param</span> <span style="color: #333;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#91;</span>Position<span style="color: #333;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>ConsoleColor<span style="color: #333;">&#93;</span></span> <span style="color: #660033; font-weight: bold;">$Color</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#91;</span>Position<span style="color: #333;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Mandatory<span style="color: #333;">&#93;</span></span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>ValueFromPipeline<span style="color: #333;">&#93;</span></span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">String</span><span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#93;</span></span> <span style="color: #660033; font-weight: bold;">$InputObject</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">BEGIN</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$CommandLineParameters</span>.<span style="color: #003366;">ContainsKey</span><span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;InputObject&quot;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Don't do anything here, because we're about to get re-invoked...</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$FromArgs</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$true</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Normal &quot;run-once&quot; BEGIN processing</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$FromArgs</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$false</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Verbose</span></span> <span style="color: #009900;">&quot;Begin $Color&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">PROCESS</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># We no longer have to test for $_ or even to see if the [ValueFromPipeline] param is set</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># It *HAS* to be set, because it's a [Mandatory] parameter :)</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$FromArgs</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Don't do anything here except re-invoke ourselves.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Output</span></span> <span style="color: #660033; font-weight: bold;">$InputObject</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">&amp;</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$MyInvocation</span>.<span style="color: #003366;">InvocationName</span><span style="color: #333;">&#41;</span> <span style="color: #660033; font-weight: bold;">$Color</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Normal Pipeline-friendly per-item processing</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Process: $InputObject&quot;</span> <span style="color: #000066;">-Fore</span> <span style="color: #660033; font-weight: bold;">$Color</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## You should make a practice of explicitly calling Write-Output on things</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## That's how you emit them into the pipeline instead of just printing them</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Output</span></span> <span style="color: #660033; font-weight: bold;">$InputObject</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">END</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$FromArgs</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span> &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Don't do anything here ... it just confuses things</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Normal &quot;run-once&quot; END processing</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Verbose</span></span> <span style="color: #009900;">&quot;End $Color&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<h4>A test case</h4>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666666; font-style: italic;">## Test Script:</span><br />
<span style="color: #666666; font-style: italic;">##</span><br />
<span style="color: #666666; font-style: italic;">## &quot;a&quot;,&quot;b&quot;,&quot;c&quot; | Test-PipelineV2 &quot;Cyan&quot; -verbose</span><br />
<span style="color: #666666; font-style: italic;">## @(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;) | Test-PipelineV2 &quot;Cyan&quot; -verbose</span><br />
<span style="color: #666666; font-style: italic;">## Test-PipelineV2 &quot;Cyan&quot; @(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;) -verbose </span><br />
<span style="color: #666666; font-style: italic;">## </span><br />
<span style="color: #666666; font-style: italic;">## &quot;a&quot;,&quot;b&quot;,&quot;c&quot; | Test-PipelineV2 &quot;Cyan&quot; -verbose | Test-PipelineV2 &quot;Green&quot; -verbose</span><br />
<span style="color: #666666; font-style: italic;">## @(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;) | Test-PipelineV2 &quot;Cyan&quot; -verbose | Test-PipelineV2 &quot;Green&quot; -verbose</span><br />
<span style="color: #666666; font-style: italic;">## Test-PipelineV2 &quot;Cyan&quot; @(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;) -verbose &nbsp;| Test-PipelineV2 &quot;Green&quot; -verbose</span><br />
<span style="color: #666666; font-style: italic;">###################################################################################################</span><br />
<span style="color: #666666; font-style: italic;">## Expected Output (sorry, no color here...)</span><br />
<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">Begin</span> Cyan<br />
<span style="color: #666699; font-weight: bold;">Process</span>: a<br />
a<br />
<span style="color: #666699; font-weight: bold;">Process</span>: b<br />
b<br />
<span style="color: #666699; font-weight: bold;">Process</span>: c<br />
c<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">End</span> Cyan<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">Begin</span> Cyan<br />
<span style="color: #666699; font-weight: bold;">Process</span>: a<br />
a<br />
<span style="color: #666699; font-weight: bold;">Process</span>: b<br />
b<br />
<span style="color: #666699; font-weight: bold;">Process</span>: c<br />
c<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">End</span> Cyan<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">Begin</span> Cyan<br />
<span style="color: #666699; font-weight: bold;">Process</span>: a<br />
a<br />
<span style="color: #666699; font-weight: bold;">Process</span>: b<br />
b<br />
<span style="color: #666699; font-weight: bold;">Process</span>: c<br />
c<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">End</span> Cyan<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">Begin</span> Cyan<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">Begin</span> Green<br />
<span style="color: #666699; font-weight: bold;">Process</span>: a<br />
<span style="color: #666699; font-weight: bold;">Process</span>: a<br />
a<br />
<span style="color: #666699; font-weight: bold;">Process</span>: b<br />
<span style="color: #666699; font-weight: bold;">Process</span>: b<br />
b<br />
<span style="color: #666699; font-weight: bold;">Process</span>: c<br />
<span style="color: #666699; font-weight: bold;">Process</span>: c<br />
c<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">End</span> Cyan<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">End</span> Green<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">Begin</span> Cyan<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">Begin</span> Green<br />
<span style="color: #666699; font-weight: bold;">Process</span>: a<br />
<span style="color: #666699; font-weight: bold;">Process</span>: a<br />
a<br />
<span style="color: #666699; font-weight: bold;">Process</span>: b<br />
<span style="color: #666699; font-weight: bold;">Process</span>: b<br />
b<br />
<span style="color: #666699; font-weight: bold;">Process</span>: c<br />
<span style="color: #666699; font-weight: bold;">Process</span>: c<br />
c<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">End</span> Cyan<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">End</span> Green<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">Begin</span> Green<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">Begin</span> Cyan<br />
<span style="color: #666699; font-weight: bold;">Process</span>: a<br />
<span style="color: #666699; font-weight: bold;">Process</span>: a<br />
a<br />
<span style="color: #666699; font-weight: bold;">Process</span>: b<br />
<span style="color: #666699; font-weight: bold;">Process</span>: b<br />
b<br />
<span style="color: #666699; font-weight: bold;">Process</span>: c<br />
<span style="color: #666699; font-weight: bold;">Process</span>: c<br />
c<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">End</span> Cyan<br />
VERBOSE: <span style="color: #666699; font-weight: bold;">End</span> Green</div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/powershell-20-ctp-script-cmdlets/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Writing Cmdlets for the PowerShell Pipeline</title>
		<link>http://huddledmasses.org/writing-cmdlets-for-the-powershell-pipeline/</link>
		<comments>http://huddledmasses.org/writing-cmdlets-for-the-powershell-pipeline/#comments</comments>
		<pubDate>Tue, 06 Nov 2007 05:25:57 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Cmdlet]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[SourceCode]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/writing-cmdlets-for-the-powershell-pipeline/</guid>
		<description><![CDATA[In a continuation of what is, sadly, becoming a series on how the PowerShell Pipeline works &#8230; Karl Prosser brought to my attention that certain powershell commands which have an -InputObject parameter don&#8217;t actually work when you pass something into it &#8230; so I thought I should create a cmdlet to show you how to [...]]]></description>
			<content:encoded><![CDATA[	<p>In a continuation of what is, <em>sadly</em>, becoming a series on how the <a href="/tag/Pipeline">PowerShell Pipeline</a> works &#8230; <a href="http://powershelllive.com/members/karl.aspx">Karl Prosser</a> brought to my attention that certain powershell commands which have an -InputObject parameter don&#8217;t actually work when you pass something into it &#8230; so I thought I should create a cmdlet to show you how to correctly handle the <code>InputObject</code> parameter with the <code>ValueFromPipeline</code> set so you can pass the input in either way.  </p>

	<h4>To demonstrate the problem, try this:</h4>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #660033; font-weight: bold;">$a</span> <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;A&quot;</span>,<span style="color: #009900;">&quot;B&quot;</span>,<span style="color: #009900;">&quot;A&quot;</span>,<span style="color: #009900;">&quot;C&quot;</span><span style="color: #333;">&#41;</span><br />
<span style="color: #660033; font-weight: bold;">$a</span> <span style="color: #66cc66;">|</span> <span style="color: #660033;">Select</span> <span style="color: #000066;">-First</span> <span style="color: #cc66cc;">3</span> <span style="color: #000066;">-Unique</span><br />
<span style="color: #660033;">Select</span> <span style="color: #000066;">-First</span> <span style="color: #cc66cc;">3</span> <span style="color: #000066;">-Unique</span> <span style="color: #000066;">-InputObject</span> <span style="color: #660033; font-weight: bold;">$a</span> </div>

	<p>This should expose two weirdnesses about how the <code>Select-Object</code> cmdlet works: </p>

	<ol>
		<li>The -First parameter affects the input before the -Unique parameter does.</li>
	</ol>
	<ol>
		<li>When you pass the input in via -InputObject, the whole array is treated as a single object, and the command basically doesn&#8217;t do anything.</li>
	</ol>

	<p>The big problem with this behavior is that there&#8217;s essentially no hint that you&#8217;ve done something wrong &#8212; there&#8217;s actually no way to make Select-Object work properly <strong>except</strong> by passing the objects in via the pipeline.  The bigger problem is that it would have been simple for the Microsoft team to catch this and alert you, but they didn&#8217;t &#8212; so you probably won&#8217;t even notice there&#8217;s a problem until you run it on a trivial data set like my example.  The even <strong>bigger problem</strong> is that it doesn&#8217;t just affect Select-Object (try it with Where-Object, just for instance). <span id="more-458"></span></p>

	<h4>The simplest fix</h4>

	<p>When this came up in the #PowerShell <span class="caps">IRC</span> channel <a href="http://nivot.org">Oisin</a> initially defended this as an unavoidable side effect of the way the cmdlet system works. However, after playing with the idea for a bit, we found it&#8217;s actually trivial to stop, although I found it hard to explain without actually <a href="/wordpress/wp-content/uploads/2007/11/testpipelinecommand1.cs">demonstrating an alternative</a>. The simplest possible alternative is just to throw an exception if the value is passed in as an argument instead of via the pipeline. That would preserve the same level of functionality you have now &#8212; but cause an error in those cases where it wouldn&#8217;t work anyway.</p>

	<div class="csharp code csharp" style="font-family:monospace;"><br />
<span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> BeginProcessing<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>_input <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">throw</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ArgumentException<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;You must pass InputObject via the pipeline!&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp;<span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">BeginProcessing</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">&#125;</span></div>

	<h4>A better way to handle input</h4>

	<p>Of course, you can do better than that  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';)' class='wp-smiley' /> .  So, I hereby present the first version of my <a href="/wordpress/wp-content/uploads/2007/11/testpipelinecommand2.cs">PowerShell Pipeline Template Cmdlet</a>.  It&#8217;s pretty simple really (once you get past all the cmdlet overhead): basically, you check in the <code>BeginProcess()</code> method to see if the <code>InputObject</code> parameter has been set, and set an alternate private variable. Then, in the <code>ProcessRecord()</code> method, we have two alternate computation paths: the normal path, and a second path for when the collection is passed in as an argument.  In that case, you recurse and call the ProcessRecord method once for each item in the collection.</p>

	<p>I&#8217;m sure some of you will have some improvements you can make, feel free to continue the development on the PowerShell Central <a href="http://powershellcentral.com/scripts/43">scripts page</a> or by sending feedback in the form below, but for now, here&#8217;s <a href="/wordpress/wp-content/uploads/2007/11/testpipelinecmdlet.7z">the Test-Pipeline Cmdlet Binary</a> and the <a href="/wordpress/wp-content/uploads/2007/11/testpipelinecommand2.cs">source code</a>.</p>

	<h4>The Code</h4>

	<div class="csharp code csharp" style="font-family:monospace;"><br />
<span style="color: #008080; font-style: italic;">// An improvement! Now we accept a single object (like Select-Object does)</span><br />
<span style="color: #008080; font-style: italic;">// But, unlike Select-Object, if an array is passed into the argument -InputObject </span><br />
<span style="color: #008080; font-style: italic;">// we still manage to process each item in the array, as we would in the pipeline</span><br />
<span style="color: #008080; font-style: italic;">//</span><br />
<span style="color: #008080; font-style: italic;">// Try it out: &nbsp; &quot;a&quot;,&quot;b&quot;,&quot;c&quot;| Test-Pipeline -verbose</span><br />
<span style="color: #008080; font-style: italic;">// Versus this: &nbsp;Test-Pipeline -verbose -input @(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;)</span><br />
<span style="color: #008080; font-style: italic;">//</span><br />
<span style="color: #008080; font-style: italic;">// If you don't set the -verbose flag, you shouldn't be able to tell them apart</span><br />
<span style="color: #008080; font-style: italic;">// The first way, the &quot;1&quot; invocation hits ProcessRecord for &quot;a&quot; </span><br />
<span style="color: #008080; font-style: italic;">// ... before the &quot;2&quot; invocation hits BeginProcessing()</span><br />
<span style="color: #008080; font-style: italic;">//</span><br />
<span style="color: #008080; font-style: italic;">// Version History</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp;1.0 Just throws an exception</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp;2.0 Finds a way to enumerate ProcessRecord from BeginProcessing</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp;There is still a slight difference, which you can see if you test these:</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Test-Pipeline 1 -input @(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;) -verbose | Test-Pipeline 2 -verbose</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;a&quot;,&quot;b&quot;,&quot;c&quot; | Test-Pipeline 1 -verbose | Test-Pipeline 2 -verbose</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp;2.3 Recursed from inside ProcessRecord instead of BeginProcessing</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp;Makes the execution look identical in the test case from 2.0</span><br />
<span style="color: #008080; font-style: italic;">////////////////////////////////////////////////////////////////////////////////</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections.Generic</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Text</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Management.Automation</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections</span><span style="color: #008000;">;</span><br />
<br />
<span style="color: #0600FF;">namespace</span> Huddled.<span style="color: #0000FF;">TestSnapin</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Cmdlet<span style="color: #000000;">&#40;</span>VerbsDiagnostic.<span style="color: #0000FF;">Test</span>, <span style="color: #666666;">&quot;Pipeline&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> TestPipelineCommand <span style="color: #008000;">:</span> Cmdlet<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">#region Parameters</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">/// This is just a name parameter for decorating test cases :)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span>Position <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mandatory <span style="color: #008000;">=</span> <span style="color: #0600FF;">false</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ValueFromPipelineByPropertyName <span style="color: #008000;">=</span> <span style="color: #0600FF;">false</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HelpMessage <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;A Name for Verbose output&quot;</span><span style="color: #000000;">&#41;</span>, ValidateNotNullOrEmpty<span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Name<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> _name<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set <span style="color: #000000;">&#123;</span> _name <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> _name <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;TestPipeline&quot;</span><span style="color: #008000;">;</span><br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span>Position <span style="color: #008000;">=</span> <span style="color: #FF0000;">1</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mandatory <span style="color: #008000;">=</span> <span style="color: #0600FF;">true</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ValueFromPipeline <span style="color: #008000;">=</span> <span style="color: #0600FF;">true</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HelpMessage <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;Help Text&quot;</span><span style="color: #000000;">&#41;</span>, ValidateNotNullOrEmpty<span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">object</span> InputObject<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> _input<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set <span style="color: #000000;">&#123;</span> _input <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">object</span> _input<span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">bool</span> _isArgument <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">#endregion</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> BeginProcessing<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteVerbose<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">String</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Begin Processing {0}&quot;</span>, Name<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>_input <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">&amp;&amp;</span> _input <a href="http://www.google.com/search?q=is+msdn.microsoft.com"><span style="color: #008000;">is</span></a> ICollection<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _isArgument <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StringBuilder output <span style="color: #008000;">=</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> StringBuilder<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;There's input: &quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> _in <span style="color: #0600FF;">in</span> <span style="color: #000000;">&#40;</span>ICollection<span style="color: #000000;">&#41;</span>_input<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.<span style="color: #0000FF;">AppendFormat</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;{0}, &quot;</span>, _in<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteVerbose<span style="color: #000000;">&#40;</span>output.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">BeginProcessing</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> ProcessRecord<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>_isArgument<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// This is the normal ProcessRecord code</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteVerbose<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">String</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Process: {0}&quot;</span>, _input<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteObject<span style="color: #000000;">&#40;</span>_input<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// This is what we have to do unwrap -InputObject as Arg</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ICollection _collection <span style="color: #008000;">=</span> _input<span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _isArgument <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">// unset isCollection before recursing</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> _in <span style="color: #0600FF;">in</span> <span style="color: #000000;">&#40;</span>ICollection<span style="color: #000000;">&#41;</span>_collection<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; InputObject <span style="color: #008000;">=</span> _in<span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ProcessRecord<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> EndProcessing<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteVerbose<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">String</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;End Processing {0}&quot;</span>, Name<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">EndProcessing</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/writing-cmdlets-for-the-powershell-pipeline/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Writing Better Script Functions for the PowerShell Pipeline</title>
		<link>http://huddledmasses.org/writing-better-script-functions-for-the-powershell-pipeline/</link>
		<comments>http://huddledmasses.org/writing-better-script-functions-for-the-powershell-pipeline/#comments</comments>
		<pubDate>Fri, 26 Oct 2007 04:41:59 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PowerShell Functions]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/writing-better-script-functions-for-the-powershell-pipeline/</guid>
		<description><![CDATA[I wrote a post last week about how to write functions for use in the PowerShell pipeline and I&#8217;ve been using the template I wrote in that post as the basis for several of my other scripts &#8230; and I&#8217;ve been gradually fleshing it out, and improving it, so I thought I&#8217;d drop it here [...]]]></description>
			<content:encoded><![CDATA[	<p>I wrote a post last week about how to <a href="/using-script-functions-in-the-powershell-pipeline/">write functions for use in the PowerShell pipeline</a> and I&#8217;ve been using the template I wrote in that post as the basis for several of my other scripts &#8230; and I&#8217;ve been gradually fleshing it out, and improving it, so I thought I&#8217;d drop it here with all of it&#8217;s inline comments.  Hopefully that will be better than what you would get if I just trying to explain it in a blog post  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' /> .</p>

	<p>Incidentally, this script is also on <a href="http://powershellcentral.com/scripts/36">PowerShellCentral scripts Repository</a> where I will probably post any future modifications &#8230; <span id="more-454"></span></p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666666; font-style: italic;">## A Template for functions which can _also_ be executed in the pipeline ....</span><br />
<span style="color: #666666; font-style: italic;">## &nbsp; by Joel Bennett, in hopes it will help...</span><br />
<span style="color: #666666; font-style: italic;">## Version History</span><br />
<span style="color: #666666; font-style: italic;">## v1.0 First public release (after over 9 different versions in my various other functions)</span><br />
<span style="color: #666666; font-style: italic;">## v1.2 Show the use of Write-Output, and change &quot;return&quot; in the BEGIN to &quot;Write-Output&quot; to avoid</span><br />
<span style="color: #666666; font-style: italic;">## &nbsp; &nbsp; &nbsp;the pooling of the output from the process block when it's invoked as a function.</span><br />
<span style="color: #666666; font-style: italic;">## v1.3 Switched back to &quot;break&quot; instead of &quot;return&quot; so that if you pass via the pipeline AND via</span><br />
<span style="color: #666666; font-style: italic;">## &nbsp; &nbsp; &nbsp;the inputObject, only the inputObject gets process (this is how cmdlets behave).</span><br />
<span style="color: #666666; font-style: italic;">###################################################################################################</span><br />
<span style="color: #666666; font-style: italic;">## The simplest thing is to make -inputObject the very last argument and make sure that you name </span><br />
<span style="color: #666666; font-style: italic;">## each parameter that you expect to see ... as always you'll have to specify a value for each </span><br />
<span style="color: #666666; font-style: italic;">## parameter, or specifically name the inputObject parameter.</span><br />
<span style="color: #666666; font-style: italic;">##</span><br />
<br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">Pipeline</span></span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Parameter1</span><span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$null</span>, <span style="color: #660033; font-weight: bold;">$inputObject</span><span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$null</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">BEGIN</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$inputObject</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">### If you're accepting $args, you need to pass those in...</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Write-Output $io | &amp;($MyInvocation.InvocationName) $args;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Output</span></span> <span style="color: #660033; font-weight: bold;">$inputObject</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">&amp;</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$MyInvocation</span>.<span style="color: #003366;">InvocationName</span><span style="color: #333;">&#41;</span> <span style="color: #660033; font-weight: bold;">$Parameter1</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">break</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">else</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#123;</span> &nbsp;<span style="color: #666666; font-style: italic;">## DO ONCE: (on the re-invoke when using -inputObject)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">host</span></span> <span style="color: #009900;">&quot;Begin $Parameter1 $args&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">PROCESS</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">## You have to at least make sure it's got a value </span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">## Really you should check it's TYPE to make sure you can do something useful...</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$_</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Write-HOST: $_&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## You should make a practice of explicitly calling Write-Output on things</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## That's how you emit them into the pipeline instead of just printing them</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Output</span></span> <span style="color: #009900;">&quot;Write-OUTPUT $_&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Most of the time, piping to Out-Default is a lot like using Write-Host...</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&quot;Out-Default $_&quot;</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Out-<span style="font-style: normal;">Default</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">END</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #66cc66;">-</span><span style="color: #333399; font-weight: bold; font-style: italic;">not</span> <span style="color: #660033; font-weight: bold;">$inputObject</span><span style="color: #333;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#123;</span> &nbsp;<span style="color: #666666; font-style: italic;">## DO ONCE: (on the re-invoke when using -inputObject)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$x</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$args</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$x</span><span style="color: #66cc66;">++</span>; <span style="color: #009900;">&quot;$x - $_&quot;</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">host</span></span> <span style="color: #009900;">&quot;End&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">###################################################################################################</span><br />
<span style="color: #666666; font-style: italic;">## Sample call:</span><br />
<span style="color: #666666; font-style: italic;">##</span><br />
<span style="color: #666666; font-style: italic;">## [1]&gt; Test-Pipeline Foo! @(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;)</span><br />
<span style="color: #666666; font-style: italic;">## Begin Foo!</span><br />
<span style="color: #666666; font-style: italic;">## Write-HOST: one</span><br />
<span style="color: #666666; font-style: italic;">## Write-OUTPUT one</span><br />
<span style="color: #666666; font-style: italic;">## Out-Default one</span><br />
<span style="color: #666666; font-style: italic;">## Write-HOST: two</span><br />
<span style="color: #666666; font-style: italic;">## Write-OUTPUT two</span><br />
<span style="color: #666666; font-style: italic;">## Out-Default two</span><br />
<span style="color: #666666; font-style: italic;">## Write-HOST: three</span><br />
<span style="color: #666666; font-style: italic;">## Write-OUTPUT three</span><br />
<span style="color: #666666; font-style: italic;">## Out-Default three</span><br />
<span style="color: #666666; font-style: italic;">## End</span><br />
<br />
<span style="color: #666666; font-style: italic;">## [2]&gt; &quot;one&quot;, &quot;two&quot;, &quot;three&quot; | Test-Pipeline Foo!</span><br />
<span style="color: #666666; font-style: italic;">## Begin Foo!</span><br />
<span style="color: #666666; font-style: italic;">## Write-HOST: one</span><br />
<span style="color: #666666; font-style: italic;">## Write-OUTPUT one</span><br />
<span style="color: #666666; font-style: italic;">## Out-Default one</span><br />
<span style="color: #666666; font-style: italic;">## Write-HOST: two</span><br />
<span style="color: #666666; font-style: italic;">## Write-OUTPUT two</span><br />
<span style="color: #666666; font-style: italic;">## Out-Default two</span><br />
<span style="color: #666666; font-style: italic;">## Write-HOST: three</span><br />
<span style="color: #666666; font-style: italic;">## Write-OUTPUT three</span><br />
<span style="color: #666666; font-style: italic;">## Out-Default three</span><br />
<span style="color: #666666; font-style: italic;">## End</span><br />
<br />
<span style="color: #666666; font-style: italic;">## ## ## To demonstrate the point of output, assign the value, or pipe it into something...</span><br />
<span style="color: #666666; font-style: italic;">## [3]&gt; $pipeline = &quot;one&quot;, &quot;two&quot;, &quot;three&quot; | Test-Pipeline Foo!</span><br />
<span style="color: #666666; font-style: italic;">## Begin Foo!</span><br />
<span style="color: #666666; font-style: italic;">## Write-HOST: one</span><br />
<span style="color: #666666; font-style: italic;">## Out-Default one</span><br />
<span style="color: #666666; font-style: italic;">## Write-HOST: two</span><br />
<span style="color: #666666; font-style: italic;">## Out-Default two</span><br />
<span style="color: #666666; font-style: italic;">## Write-HOST: three</span><br />
<span style="color: #666666; font-style: italic;">## Out-Default three</span><br />
<span style="color: #666666; font-style: italic;">## End</span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/writing-better-script-functions-for-the-powershell-pipeline/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Script Functions in the PowerShell Pipeline</title>
		<link>http://huddledmasses.org/using-script-functions-in-the-powershell-pipeline/</link>
		<comments>http://huddledmasses.org/using-script-functions-in-the-powershell-pipeline/#comments</comments>
		<pubDate>Fri, 19 Oct 2007 20:09:47 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PowerShell Functions]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/using-script-functions-in-the-powershell-pipeline/</guid>
		<description><![CDATA[Update, I created a better version of a pipeline function for powershell &#8230; 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&#8217;m sure others have already written this up on the web in the past, [...]]]></description>
			<content:encoded><![CDATA[	<p> <img src='http://huddledmasses.org/wordpress/wp-includes/' alt='[new]' class='wp-smiley' />  Update, I created <a href="/writing-better-script-functions-for-the-powershell-pipeline/">a better version of a pipeline function for powershell</a> &#8230;</p>

	<p>Every once in a while the question of how to best use the <strong>process</strong> block of a function to process pipeline objects comes up on <span class="caps">IRC</span>, and although I&#8217;m sure others have already written this up on the web in the past, we&#8217;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&#8217;s about time to publish it a little more prominently.</p>

	<p>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&#8217;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&#8217;s not really supported.  In addition, we require that the function process items as they come in, rather than waiting until it&#8217;s received all input before processing them.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Test-<span style="font-style: normal;">Pipeline</span></span><span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$inputObject</span>,<span style="color: #660033; font-weight: bold;">$io</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">BEGIN</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$inputObject</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><span style="color: #660033; font-weight: bold;">$io</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">&amp;</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$MyInvocation</span>.<span style="color: #003366;">InvocationName</span><span style="color: #333;">&#41;</span> <span style="color: #660033; font-weight: bold;">$args</span>; <span style="color: #666699; font-weight: bold;">break</span>;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$args</span> <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$io</span><span style="color: #333;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #660033; font-weight: bold;">$args</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">host</span></span> <span style="color: #009900;">&quot;Begin $args&quot;</span><br />
&nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">PROCESS</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">write-<span style="font-style: normal;">host</span></span> <span style="color: #009900;">&quot;PROCESSME: $_&quot;</span><br />
&nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">END</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$x</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$args</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$x</span><span style="color: #66cc66;">++</span>; <span style="color: #009900;">&quot;$x - $_&quot;</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">host</span></span> <span style="color: #009900;">&quot;End&quot;</span><br />
&nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span></div>

	<h4>Some explanation</h4>

	<p>This is just an example method, it doesn&#8217;t really do much, except that it outputs exactly the same thing whether you call it like <code>Test-Pipeline -inputObject &#34;Foo&#34;,&#34;Bar&#34;,&#34;Baz&#34; &#34;Kill Each Process&#34;</code> or like: <code>&#34;&#34;Foo&#34;,&#34;Bar&#34;,&#34;Baz&#34; | Test-Pipeline &#34;Kill Each Process&#34;</code>.    </p>

	<p>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 <code>process</code> block <em>must</em> remain the first line, even if you add additional code to the block.  </p>

	<p>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&#8217;t expect values, so we&#8217;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 <em>behave</em> rather like a cmdlet would, but it&#8217;s a little delicate: if you&#8217;re going to pass input objects, you <strong>must</strong> 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.  </p>

	<p>You can also add additional named parameters &#8212; 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&#8217;t specified.</p>

	<p>Here&#8217;s some sample output, in case you&#8217;re wondering:</p>

	<div class="text code text" style="font-family:monospace;"><br />
PS&gt; $foo = &quot;Greetings&quot;,&quot;Earthling&quot;<br />
PS&gt; $foo | Template-Pipeline &quot;Hello&quot; &quot;World&quot;<br />
Begin Hello World<br />
PROCESSME: Greetings<br />
PROCESSME: Earthling<br />
1 - Hello<br />
2 - World<br />
End<br />
PS&gt; Template-Pipeline -in $foo &quot;Hello&quot; &quot;World&quot;<br />
Begin Hello World<br />
PROCESSME: Greetings<br />
PROCESSME: Earthling<br />
1 - Hello<br />
2 - World<br />
End<br />
&nbsp;</div>

	<h4>Credit where it&#8217;s due</h4>

	<p>I wanted to officially acknowledge that <a href="http://thepowershellguy.com/blogs/posh/">/\/\o\/\/</a> and <a href="http://thepowershellguy.com/blogs/gaurhoth/">Gaurhoth</a> and <a href="http://www.nivot.org/">Oisin</a> and <a href="http://bsonposh.com/">Brandon</a> have all contributed to the polishing and testing of this script in various forms &#8230; thanks to all  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';-)' class='wp-smiley' /> </p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/using-script-functions-in-the-powershell-pipeline/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

