简体   繁体   中英

Pass Cmdlet as parameter to Function

There are a couple good answers about passing functions

function pass_function([scriptblock] $func, [int] $a){
  func.invoke($a)
}

How would you pass Cmdlets that accept piped input? I have a poor solution

function pass_through([scriptblock]$command){
  $command.invoke()
}

1,2,3,4 | pass_through { $input | Where { $_ -gt 1} }

outputs 2, 3, 4.

Technically there are enough tools there, but they require implementation fiddling. I would prefer to pass Where and {$_ -gt 1} as separate parameters.

If there isn't good support for this, what is this language's style for solving similar problems?

So the problem is that different cmdlets are going to have different ways to invoke them. Such as, passing 1,2,3,4 to a Where clause is fine, it likes arrays of just about anything, but you can't pass that to Format-Table because it simply doesn't take an array of strings, it needs an array of objects.

For your Where purpose you could do something like:

Function Pass_Through {
Param(
    [string]$Cmd,
    [string]$Arguments
)
Process{[scriptblock]::Create("`$input|$cmd $arguments").Invoke()}
}

Then when we do:

1,2,3,4 | pass_through 'Where' '{ $_ -gt 1}'

It responds with 2, 3, 4 as expected. But what happens when you want to pass an object and not a string?

Get-ADUser $env:USERNAME | Pass_Through 'Format-Table' 'Name,DistinguishedName'

Not going to happen, because it tries to extrapolate each property and pass each string to the Format-Table cmdlet, and that just doesn't work.

Looks like you are looking for a way to change command in the middle of pipeline without writing another copy of pipeline. You can achieve that by invoking ScriptBlock as SteppablePipeline . Nice thing is that Invoke-Command cmdlet can do that for you, if all following conditions are meet:

  • Invoke-Command expect pipeline input.
  • ScriptBlock does not have direct reference to $input .
  • ScriptBlock convertible to SteppablePipeline .

Here is Pass_Through function:

function Pass_Through {
    param(
        [ScriptBlock]$MiddleCommand
    )
    $input|
    Pre-Command|
    Invoke-Command $MiddleCommand|
    Post-Command
}

And you can invoke it like this:

1..10|Pass_Through {Where { $_ -gt 1}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM