#requires -version 2.0 ################################################################################################### ## A Template for Script Cmdlets which can _also_ be executed in the pipeline .... ## by Joel Bennett, in hopes it will help... ## Version History ## v1.0 - First public release (after over 9 different versions in my various other functions) ## v1.2 - Show the use of Write-Output, and change "return" in the BEGIN to "Write-Output" to avoid ## the pooling of the output from the process block when it's invoked as a function. ## v1.3 - Switched back to "break" instead of "return" so that if you pass via the pipeline AND via ## the inputObject, only the inputObject gets process (this is how cmdlets behave). ## - Cleaned up the comments, and removed the confusing alternate method and $args handling ## ## v2.0 - First Version as a Script Cmdlet. ## This is much easier with support for [ValueFromPipeline] and [ValueFromPipelineByName] ## ################################################################################################### Cmdlet Test-PipelineV2 -ConfirmImpact low -snapin Huddled.Tests { Param ( [Position(0)] [ConsoleColor] $Color, [Position(1)] [Mandatory] [ValueFromPipeline] [String[]] $InputObject ) BEGIN { if ($CommandLineParameters.ContainsKey("InputObject")) { # Don't do anything here, because we're about to get re-invoked... $FromArgs = $true } else { # Normal "run-once" BEGIN processing $FromArgs = $false Write-Verbose "Begin $Color" } } PROCESS { # We no longer have to test for $_ or even to see if the [ValueFromPipeline] param is set # It *HAS* to be set, because it's a [Mandatory] parameter :) if ($FromArgs) { # Don't do anything here except re-invoke ourselves. Write-Output $InputObject | &($MyInvocation.InvocationName) $Color } else { # Normal Pipeline-friendly per-item processing Write-Host "Process: $InputObject" -Fore $Color ## You should make a practice of explicitly calling Write-Output on things ## That's how you emit them into the pipeline instead of just printing them Write-Output $InputObject } } END { if ($FromArgs) { # Don't do anything here ... it just confuses things } else { # Normal "run-once" END processing Write-Verbose "End $Color" } } } ################################################################################################### ## Test Script: ## ## "a","b","c" | Test-PipelineV2 "Cyan" -verbose ## @("a","b","c") | Test-PipelineV2 "Cyan" -verbose ## Test-PipelineV2 "Cyan" @("a","b","c") -verbose ## ## "a","b","c" | Test-PipelineV2 "Cyan" -verbose | Test-PipelineV2 "Green" -verbose ## @("a","b","c") | Test-PipelineV2 "Cyan" -verbose | Test-PipelineV2 "Green" -verbose ## Test-PipelineV2 "Cyan" @("a","b","c") -verbose | Test-PipelineV2 "Green" -verbose ## ################################################################################################### ## Expected Output: ## ## [PS]> .\Test.ps1 ## VERBOSE: Begin Cyan ## Process: a ## a ## Process: b ## b ## Process: c ## c ## VERBOSE: End Cyan ## VERBOSE: Begin Cyan ## Process: a ## a ## Process: b ## b ## Process: c ## c ## VERBOSE: End Cyan ## VERBOSE: Begin Cyan ## Process: a ## a ## Process: b ## b ## Process: c ## c ## VERBOSE: End Cyan ## VERBOSE: Begin Cyan ## VERBOSE: Begin Green ## Process: a ## Process: a ## a ## Process: b ## Process: b ## b ## Process: c ## Process: c ## c ## VERBOSE: End Cyan ## VERBOSE: End Green ## VERBOSE: Begin Cyan ## VERBOSE: Begin Green ## Process: a ## Process: a ## a ## Process: b ## Process: b ## b ## Process: c ## Process: c ## c ## VERBOSE: End Cyan ## VERBOSE: End Green ## VERBOSE: Begin Green ## VERBOSE: Begin Cyan ## Process: a ## Process: a ## a ## Process: b ## Process: b ## b ## Process: c ## Process: c ## c ## VERBOSE: End Cyan ## VERBOSE: End Green