Is there a way pass a Cmdlet with some parameters

2019-09-09 22:21发布

问题:

Building on this technique to use Cmdlets as "delegates" I am left with this question:

Is there a way to pass a commandlet with prescribed named or positional parameters to another commandlet that uses the powershell pipeline to bind the remaining parameters to the passed commandlet?

Here is the code snippet I'd like to be able to run:

Function Get-Pow{
    [CmdletBinding()] 
    Param([Parameter(ValueFromPipeline=$true)]$base,$exp)
    PROCESS{[math]::Pow($base,$exp)}
}
Function Get-Result{
    [CmdletBinding()]
    Param([Parameter(ValueFromPipeline=$true)]$x,$Cmdlet)
    $x | . $Cmdlet
}

10 | Get-Result -Cmdlet 'Get-Pow -exp 2'
10 | Get-Result -Cmdlet 'Get-Pow -exp 3'
10 | Get-Result -Cmdlet Get-Pow -exp 2
10 | Get-Result -Cmdlet Get-Pow -exp 3

The first two calls to Get-Result result in CommandNotFoundException because Get-Pow -exp 2 "is not the name of a cmdlet."

The last two calls to Get-Result result in NamedParameterNotFound,Get-Result since that syntax is actually attempting to pass parameter -exp to Get-Result which it does not have.

Is there some other way to set this up so it works?

回答1:

I'm not sure this is the best method, but at least it resembles powershell idioms throughout:

Function Get-Amount{
    [CmdletBinding()] 
    Param(
    [Parameter(ValueFromPipeline=$true)]$t,
    [Parameter(position=1)]$r,
    [Parameter(position=2)]$P)
PROCESS{$P*[math]::Pow(1+$r,$t)}
}
Function Get-Result{
    [CmdletBinding()]
    Param(
    [Parameter(ValueFromPipeline=$true)]$x,
    [Parameter(Position=1)]$Cmdlet,        #positional arguments here makes calling more readable
    [Alias('args')]                        #careful, $args is a special variable
    [Parameter(Position=2)]$Arguments=@()) #the default empty array is required for delegate style 1
PROCESS{
    #invoke style 1                        #works with delegate styles 1,2,3
    iex "$x | $Cmdlet @Arguments"          

    #invoke style 2                        #works with delegate styles 2,3
    $x | . $Cmdlet @Arguments              
}}

5,20 | Get-Result 'Get-Amount -r 0.05 -P 100' #delegate style 1
5,20 | Get-Result Get-Amount 0.05,100         #delegate style 2
5,20 | Get-Result Get-Amount @{r=0.05;P=100}  #delegate style 3

Which results in:

127.62815625
CommandNotFoundException
265.329770514442
CommandNotFoundException
127.62815625
127.62815625
265.329770514442
265.329770514442
127.62815625
127.62815625
265.329770514442
265.329770514442