Accepting Piped input

So how do take input (which is usually an array of objects) that is passed to your module?

Piping Input With PowerShell Module

You just add an attribute to the parameter.

function show-data {
    param(
        [Parameter(ValueFromPipeline=$true)] 
        $InputObject
    )

    begin {
        $objects = @()
    }

    process {
        $objects += $InputObject
    }

    end {
        foreach($obj in $objects)
        {
            $obj
            #$obj is written to the pipeline on each iteration of the loop
        }

    }
}

Get-ChildItem | show-data

Note that process is called for each item in the array being piped in. In the code snippet, we collected all the items to be processed during end

Using C# module

In C# code, this is what it looks like:

using System.Management.Automation;  //get this from nuget package manager - use PowerShellStandard.Library

[Cmdlet(VerbsDiagnostic.Test, "PipelineObjDyn")]
public class TestPipelineDynamic : Cmdlet
{

    [Parameter(ValueFromPipeline = true)]
    public dynamic ObjectFromPipeline { get; set; } //using dynamic because we don't know what type is going to be returned; using PSObject would be better.

    private List<dynamic> objects;
    protected override void BeginProcessing()
    {
        objects = new List<dynamic>();
    }

    protected override void ProcessRecord()
    {
        objects.Add(ObjectFromPipeline);
    }

    protected override void EndProcessing()
    {
        foreach (var obj in objects)
        {
            WriteObject(obj);   //writes object to the pipeline
        }
    }
}

I strongly recommend using Visual Studio to set breakpoints and see what the underlying object (ObjectFromPipeline) looks like. You’ll get a much better understanding of what’s going on.

Cmdlet development tips

When developing cmdlets (binary PS modules), you will want to convert PSObject to/from Dictionary<string,object> (or ExpandoObject)

public static class HelperExtensions
{
    public static PSObject AsPSObject(this ExpandoObject eo)
    {
        //makes it so that your C# objects can be filtered/manipulated with powershell syntax
        var newpso = new PSObject();
        var expandoAsDict = ((IDictionary<string, object>)eo);
        foreach (var k in expandoAsDict.Keys)
        {
            newpso.Members.Add(new PSNoteProperty(k, expandoAsDict[k]));
        }
        return newpso;
    }

    public static IDictionary<string,object> AsDictionary(this PSObject pso)
    {
        //makes stuff coming in from the pipeline easier to handle
        var newDict = new Dictionary<string, object>();
        foreach (var prop in pso.Properties)
        {
            newDict[prop.Name] = prop.Value;
        }
        return newDict;
    }
}

Example Cmdlet Code

Example cmdlet that reads a csv file and outputs results as an array of PSObjects

[Cmdlet(VerbsDiagnostic.Test, "WriteObject")]
public class TestBinaryModuleCmdlet1Command : Cmdlet
{
    protected override void BeginProcessing()
    {
        using (var reader = new StreamReader(@"D:\temp\test.csv"))
        {
            using (var csv = new CsvReader(reader))
            {
                var records = csv.GetRecords<dynamic>();
                foreach(var rec in records)
                {
                    WriteObject(((ExpandoObject)rec).AsPSObject());
                }
            }
        }
    }
}

CsvReader is part of the CsvHelper nuget package

get yourself on the email list

//Powered by MailChimp - low volume, no spam

comments powered by Disqus