Function Help: Default param value with pipelining

This topic contains 3 replies, has 2 voices, and was last updated by  Dave Wyatt 3 years, 6 months ago.

  • Author
    Posts
  • #14483

    Rob Simmers
    Participant

    Basically, the scenario is user is providing a CSV. We'll say there are two params First and Second. If the user does not provide a Second param in the CSV, the goal is to use the default function param. So, the function:

    Function Test-It{
    Param(
    [Parameter(Mandatory=$false,
    ValueFromPipeline=$True,
    ValueFromPipelineByPropertyName=$True,
    HelpMessage='The first parameter')]
    [AllowNull()]
    [AllowEmptyString()]
    [string]$First ="FirstDefault",
    [Parameter(Mandatory=$True,
    ValueFromPipeline=$True,
    ValueFromPipelineByPropertyName=$True,
    HelpMessage='The second parameter')]
    [AllowNull()]
    [AllowEmptyString()]
    [string]$Second ="SecondDefault" )

    begin{}
    process{
    Write-Host ("First: {0}" -f $First)
    Write-Host ("Second: {0}" -f $Second)
    }
    end{}
    }

    If I do Test-It -First "Whatever", the default works correctly. If I pass both params over the pipeline:

    $parameters = New-Object -TypeName PSObject -Property @{
    First = "Hello"
    Second = "Rob"
    }

    Clear-Host
    $parameters | Test-It

    Returns:
    First: Hello
    Second: Rob

    But if I only pass one parameter over the pipeline:

    $parameters = New-Object -TypeName PSObject -Property @{
    First = "Hello"
    }

    Clear-Host
    $parameters | Test-It

    Then it returns like this when I expect Second: SecondDefault:

    First: Hello
    Second: @{First=Hello}

    How do input default params are utilizing when using the pipeline?

  • #14484

    Dave Wyatt
    Moderator

    Try getting rid of the "ValueFromPipeline" attributes, and just stick with ValueFromPipelineByPropertyName.

  • #14485

    Rob Simmers
    Participant

    Ok, that did work. When you use the ValueFromPipeLine, is that insinuating that everything the function will need is coming from the pipleline. I'm trying to understand this behavior so I know when and when not to use that parameter option. Can you elaborate? Thank you for the quick response.

  • #14486

    Dave Wyatt
    Moderator

    Pipeline input works in one of 4 ways (attempted in this order, if I remember correctly): By Value (no coercion), By Property Name (no coercion), By Value (with coercion), By Property Name (with coercion). You've defined your two input parameters to be of type [String], but piped in a PSObject. By Value (no coercion) doesn't work, because the type of the input object doesn't match either parameter. By Propety Name (no coercion) works, for whichever properties exist as Strings on your input object. By Value (with coercion) will ALWAYS succeed for any remaining unbound String parameters, because every object can be represented as a string via the Object.ToString() method. That's where your function was running into a problem.

    Having ValueFromPipeline applied to multiple parameters in the same parameter set is usually pointless. Typically, you'll see one parameter with ValueFromPipeline (and possibly ValueFromPipelineByPropertyName as well), and any number of other parameters with ValueFromPipelineByPropertyNaem only.

You must be logged in to reply to this topic.