Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way in powershell to catch ALL named parameters

Consider this:

Function Foo 
{
    param(
        #????
    )
}

I want to call Foo like this:

Foo -Bar "test"

Without it blowing up that I don't have a $bar param specified. Is that possible? :)

Update:

I want this to work:

Function IfFunctionExistsExecute
{
    param ([parameter(Mandatory=$true)][string]$func, [parameter(Mandatory=$false)][string]$args)
    begin 
    {
        # ...
    }
    process
    {
        if(Get-Command $func -ea SilentlyContinue)
        {
            & $func $args   # the amperersand invokes the function instead of just printing the variable
        }
        else
        {
            # ignore
        }       
    }
    end
    {
        # ...
    }
}


Function Foo
{
    param([string]$anotherParam)
    process 
    {
        $anotherParam
    }
}

IfFunctionExistsExecute Foo -Test "bar"

This gives me:

IfFunctionExistsExecute : A parameter cannot be found that matches parameter name 'Test'.
At C:\PSTests\Test.ps1:35 char:34
+ IfFunctionExistsExecute Foo -Test <<<<  "bar"
    + CategoryInfo          : InvalidArgument: (:) [IfFunctionExistsExecute], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,IfFunctionExistsExecute
like image 716
Snake Avatar asked Jul 06 '12 13:07

Snake


1 Answers

I would suggest two alternatives.

First: you may want to consider passing whole function + it's parameters as scriptblock parameter to your ifFunction...

OR: use ValueFromRemainingArguments:

function Test-SelfBound {
param (
    [Parameter(
        Mandatory = $true,
        HelpMessage = 'Help!'
    )]
    [string]$First,
    [Parameter(
        ValueFromRemainingArguments = $true
    )]
    [Object[]]$MyArgs
)

$Arguments = foreach ($Argument in $MyArgs) {
    if ($Argument -match '^-([a-z]+)$') {
        $Name = $Matches[1]
        $foreach.MoveNext() | Out-Null
        $Value = $foreach.Current
        New-Variable -Name $Name -Value $Value
        $PSBoundParameters.Add($Name,$Value) | Out-Null
    } else {
        $Argument
    }
}
    $PSBoundParameters | Out-Default
    "Positional"
    $Arguments

}

Test-SelfBound -First Test -Next Foo -Last Bar Alfa Beta Gamma

In this case I use $MyArgs to store everything besides my mandatory parameter 'First'. Than some simple if will tell me if it's named parameter (-Next, -Last) or positional (Alfa, Beta, Gamma). This way you can have both advantages of advanced functions binding (whole [Parameter()] decoration) AND leave room for $args-style parameters too.

like image 154
BartekB Avatar answered Nov 15 '22 09:11

BartekB