Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a Powershell v2.0 dynamic parameter be at position 0?

I cannot find this specific question being addressed, so I'll ask it here: I cannot seem to get a dynamc parameter to be the position 0 parameter. When I try, it seems as though the first static parameter defined at position 1 will promote or inherit position 0 and the dynamic parameter defined for position 0 is then added afterward at the next available position (position 1):

    $x=[string]::Empty;

    Function foo {
        [cmdletbinding()]
        Param (
            [Parameter(ParameterSetName="set1",
                       Position=1,
                       ValueFromPipeline=$true)]
                $InputObject,
            [Parameter()]
            [switch]
                $RequireFilePath
        )
        DynamicParam {
            $mand = $script:x -eq $null -or `
                $script:x -eq [string]::Empty -or `
                $RequireFilePath.IsPresent;

            $attrs = New-Object System.Management.Automation.ParameterAttribute;
            $attrs.ParameterSetName = "set1";
            $attrs.Mandatory = $mand;
            $attrs.Position = 0;

            $attrCollection = New-Object `
                System.Collections.ObjectModel.Collection[System.Attribute];
            $attrCollection.Add($attrs);

            $FilePath = New-Object System.Management.Automation.RuntimeDefinedParameter `
                "FilePath", string, $attrCollection;

            $paramDictionary = New-Object `
                System.Management.Automation.RuntimeDefinedParameterDictionary;
            $paramDictionary.Add("FilePath", $FilePath);

            $paramDictionary;
        }
        Begin {
            if ( $FilePath.Value -eq $null -or $FilePath.Value -eq [string]::Empty) {
                $FilePath.Value = $script:x;
            } else {
                $script:x = $FilePath.Value;
            }
            Write-Output ("(foo)        FilePath: {0}" -f $FilePath.Value);
            Write-Output ("(foo) RequireFilePath: {0}" -f $RequireFilePath.IsPresent);
            Write-Output ("(foo)        script:x: {0}" -f $script:x);
        }
        Process {
            Write-Output ("(foo)     InputObject: {0}" -f $InputObject);
        }
        End {
        }
    }

    foo "filename2.txt" "zxcv";

When executed, I get this:

    (foo)        FilePath: zxcv
    (foo) RequireFilePath: False
    (foo)        script:x: zxcv
    (foo)     InputObject: filename2.txt

I suppose my expectation was that the dynamic parameter was going to be position 0 and the static parameter was going to be position 1. Can anybody weigh in on this? Is it possible to have a dynamic parameter be defined to be at a postion lower than (earlier than) a static parameter?

like image 289
jad45 Avatar asked Feb 04 '13 15:02

jad45


2 Answers

After playing around with this a little bit, I discovered that adding the ValueFromRemainingArguments Parameter Attribute to the $InputObject parameter seems to get closest to the desired behavior; however, I am not entirely sure why.

    Param (...
    [Parameter(ParameterSetName="set1",
               Position=1,
               ValueFromPipeline=$true
               ValueFromRemainingArguments=$true)]
        $InputObject,
    ...)
like image 165
jad45 Avatar answered Sep 28 '22 05:09

jad45


Another approach that worked for me is to set the PositionalBinding argument of the CmdletBinding attribute to $False. Then if only the dynamic parameters have a Position set, then they get the positional values set correctly.

This of course assumes that you don't want any of the static parameters to have a position.

like image 27
David Gardiner Avatar answered Sep 28 '22 07:09

David Gardiner