将Cmdlet作为参数传递给Function

时间:2015-11-04 23:14:44

标签: powershell

关于传递函数有几个很好的答案

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

你如何通过接受管道输入的Cmdlet?我的解决方案很差

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

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

输出2,3,4。

从技术上讲,那里有足够的工具,但它们需要实施。我更愿意将Where和{$ _ -gt 1}作为单独的参数传递。

如果对此没有很好的支持,这种语言解决类似问题的方式是什么?

2 个答案:

答案 0 :(得分:2)

所以问题是不同的cmdlet会有不同的方式来调用它们。例如,将1,2,3,4传递给Where子句是好的,它喜欢几乎所有的数组,但你不能将它传递给Format-Table因为它根本不需要一个字符串数组,它需要一个对象数组。

对于Where目的,您可以执行以下操作:

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

然后我们这样做:

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

按预期响应2,3,4。 但是当你想传递一个对象而不是一个字符串时会发生什么?

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

不会发生,因为它试图推断每个属性并将每个字符串传递给Format-Table cmdlet,而这只是不起作用。

答案 1 :(得分:2)

看起来您正在寻找一种在管道中间更改命令而无需编写另一个管道副本的方法。您可以通过将ScriptBlock调用为SteppablePipeline来实现此目的。好的是,如果满足以下所有条件,Invoke-Command cmdlet可以为您做到这一点:

  • Invoke-Command期待管道输入。
  • ScriptBlock没有直接引用$input
  • ScriptBlock可转换为SteppablePipeline

这是Pass_Through函数:

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

你可以像这样调用它:

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