//////////////////////////////////////////////////////////////////////////////// // An improvement! Now we accept a single object (like Select-Object does) // But, unlike Select-Object, if an array is passed into the argument -InputObject // we still manage to process each item in the array, as we would in the pipeline // // Try it out: "a","b","c"| Test-Pipeline -verbose // Versus this: Test-Pipeline -verbose -input @("a","b","c") // // If you don't set the -verbose flag, you shouldn't be able to tell them apart // The first way, the "1" invocation hits ProcessRecord for "a" // ... before the "2" invocation hits BeginProcessing() // // Version History // 1.0 Just throws an exception // 2.0 Finds a way to enumerate ProcessRecord from BeginProcessing // There is still a slight difference, which you can see if you test these: // Test-Pipeline 1 -input @("a","b","c") -verbose | Test-Pipeline 2 -verbose // "a","b","c" | Test-Pipeline 1 -verbose | Test-Pipeline 2 -verbose // 2.3 Recursed from inside ProcessRecord instead of BeginProcessing // Makes the execution look identical in the test case from 2.0 //////////////////////////////////////////////////////////////////////////////// using System; using System.Collections.Generic; using System.Text; using System.Management.Automation; using System.Collections; namespace Huddled.TestSnapin { [Cmdlet(VerbsDiagnostic.Test, "Pipeline")] public class TestPipelineCommand : Cmdlet { #region Parameters /// /// This is just a name parameter for decorating test cases :) /// [Parameter(Position = 0, Mandatory = false, ValueFromPipelineByPropertyName = false, HelpMessage = "A Name for Verbose output"), ValidateNotNullOrEmpty] public string Name { get { return _name; } set { _name = value; } } private string _name = "TestPipeline"; [Parameter(Position = 1, Mandatory = true, ValueFromPipeline = true, HelpMessage = "Help Text"), ValidateNotNullOrEmpty] public object InputObject { get { return _input; } set { _input = value; } } private object _input; private bool _isArgument = false; #endregion protected override void BeginProcessing() { WriteVerbose(String.Format("Begin Processing {0}", Name)); if (_input != null && _input is ICollection) { _isArgument = true; StringBuilder output = new StringBuilder("There's input: "); foreach (object _in in (ICollection)_input) { output.AppendFormat("{0}, ", _in); } WriteVerbose(output.ToString()); } base.BeginProcessing(); } protected override void ProcessRecord() { if (!_isArgument) { // This is the normal ProcessRecord code WriteVerbose(String.Format("Process: {0}", _input)); WriteObject(_input); } else { // This is what we have to do unwrap -InputObject as Arg ICollection _collection = _input; _isArgument = false; // unset isCollection before recursing foreach (object _in in (ICollection)_collection) { InputObject = _in; ProcessRecord(); } } } protected override void EndProcessing() { WriteVerbose(String.Format("End Processing {0}", Name)); base.EndProcessing(); } } }