Search code examples
c#powershellpowershell-cmdletselect-object

PowerShell problem using Select-Object with C# cmdlet


I've written a simple C# cmdlet, let's call it Get-Data, that returns an array of objects.

protected override void ProcessRecord() {
    base.ProcessRecord();

    DummyClass[] refs = new DummyClass[2];
    refs[0] = new DummyClass("A", "big");
    refs[1] = new DummyClass("B", "small");

    base.WriteObject(refs);
    return;
}

This is the definition of DummyClass:

public class DummyClass {
    public string Name { get; set; }
    public string Type { get; set; }
    public DummyClass(string name, string  type) {
        this.Name = name;
        this.Type = type;
    }
}

When I run the cmdlet by itself, I get the expected output - one row that has column headings and an additional row for each element of the array.

PS> Get-Data

Name Type
---- ----
A    big
B    small

However, when I pipe the output to Select-Object, I see column headings, but no data rows.

PS> Get-Data | Select-Object -Property Name,Type

Name Type
---- ----

I've even tried specifying the number of rows, with no luck:

PS> Get-Data | Select-Object -Property Name,Type -Last 2

Checking the type of Get-Data returns a data type of DummyClass[], which is what I'd expect.

(Get-Data).GetType().FullName

Does anyone have any thoughts on why there are no data rows when I use Select-Object? I don't know if it matters, but this cmdlet inherits from System.Management.Automation.PSCmdlet.


Solution

  • The reason it doesn't work is that DummyClass[] doesn't have a Name or Type property, since it's an array. You can force it to unravel by nesting pipelines:

    (Get-Data) |Select-Object Name,Type
    

    Change this line:

    base.WriteObject(refs);
    

    to

    base.WriteObject(refs, true);
    

    to fix the default behavior.

    The second argument (enumerateCollection) makes the command runtime unravel your array before sending it downstream to the next cmdlet in the pipeline.