Hand-E-Food
Hand-E-Food

Reputation: 12794

Getting different results using the pipeline with functions

I'm finding that passing objects to functions through the PowerShell pipeline converts them to string objects. If I pass the object as a parameter it keeps its type. To demonstrate:

I have the following PowerShell function which displays a object's type and value:

function TestFunction {
    param (
        [Parameter(
            Position=0,
            Mandatory=$true,
            ValueFromPipeline=$true
        )] $InputObject
    )

    Echo $InputObject.GetType().Name
    Echo $InputObject
}

I ran this script to test the function:

[string[]] $Array = "Value 1", "Value 2"

# Result outside of function.
Echo $Array.GetType().Name
Echo $Array
Echo ""

# Calling function with parameter.
TestFunction $Array
Echo ""

# Calling function with pipeline.
$Array | TestFunction

This produces the output:

String[]
Value 1
Value 2

String[]
Value 1
Value 2

String
Value 2

EDIT: How can I use the pipeline to pass an entire array to a function?

Upvotes: 7

Views: 2143

Answers (3)

Shay Levy
Shay Levy

Reputation: 126712

In addition to having a process block you also need to process each item in the array. It is needed when the array is passed as an argument, not via piping. Consider this:

function Test-Function 
{
    param (
        [Parameter(
            Position=0,
            Mandatory=$true,
            ValueFromPipeline=$true
        )] $InputObject
    )

    process
    {
        $InputObject.GetType().Name
    }
}

$Array = "Value 1","Value 2"
Test-Function $array

The result would be String[], which is probably not what you want. The following command will print the type of each item in the array no matter how the argument is passed:

function Test-Function 
{
    param (
        [Parameter(
            Position=0,
            Mandatory=$true,
            ValueFromPipeline=$true
        )] $InputObject
    )

    process
    {
        foreach($i in $InputObject)
        {
            $i.GetType().Name
        }
    }
}

Upvotes: 3

Cory
Cory

Reputation: 12814

Have you tried passing something that is not a string into that function?

Try out: 1, 2 | TestFunction

EDIT:

Try this. The only change I made was to add a process block around $InputObject

function TestFunction {
    param (
        [Parameter(
            Position=0,
            Mandatory=$true,
            ValueFromPipeline=$true
        )] $InputObject
    )

    process
    {
    Echo $InputObject.GetType().Name
    Echo $InputObject
    }
}

Upvotes: 0

Andy Arismendi
Andy Arismendi

Reputation: 52567

To process multiple items recieved via the pipeline you need a process block in your function:

function Test-Function {
    param (
        [Parameter(ValueFromPipeline=$true)] $Test
    )

    process {
        $Test.GetType().FullName
        $Test
    }
}

[string[]] $Array = "Value 1", "Value 2"
$Array | Test-Function

More info:

Upvotes: 7

Related Questions