PowerShell中的包装函数:传递剩余参数

时间:2011-09-14 11:54:00

标签: powershell parameters

我正在尝试在PowerShell中编写一个包装器函数,该函数基本上评估第一个参数并基于它在计算机上运行程序。然后,包装函数的所有剩余参数都应传递给运行的程序。

所以看起来应该是这样的:

function test ( [string] $option )
{
    if ( $option -eq 'A' )
    {
        Write-Host $args
    }
    elseif ( $option -eq 'B' )
    {
        . 'C:\Program Files\some\program.exe' $args
    }
}

现在只添加$args不起作用,那么我需要做些什么才能使其正常工作?另一种选择可能是使用Invoke-Expression,但感觉有点像eval所以我想尽可能避免,此外我认为这样做会限制我只使用字符串参数吧?如果可能的话,我希望得到对包装程序/ cmdlet的完全支持 - 基本上就像动态别名一样。这甚至可能吗?

3 个答案:

答案 0 :(得分:11)

这样做可以满足您的要求。如果您需要将带有破折号前缀的选项传递给与PowerShell常见参数冲突或导致歧义的可执行文件,则可能会遇到麻烦。但这可能会让你开始。

function Invoke-MyProgram
{
    [CmdletBinding()]
    Param
    (
        [parameter(mandatory=$true, position=0)][string]$Option,
        [parameter(mandatory=$false, position=1, ValueFromRemainingArguments=$true)]$Remaining
    )

    if ($Option -eq 'A')
    {
        Write-Host $Remaining
    }
    elseif ($Option -eq 'B')
    {
        & 'C:\Program Files\some\program.exe' @Remaining # NOTE: @ not $ (splatting)
    }
}

答案 1 :(得分:3)

您所写的内容(else if处的语法错误除外 - 它应该是elseif)确实有效。请注意,$args的含义是超出函数预期参数的未命名参数。

因此,如果您将测试称为

test -option "A" 1 2 3

$args1,2,3

请注意,如果您将测试称为

test -option "A" -other "B" 1 2 3

$args-other,B,1,2,3

答案 2 :(得分:1)

  • 您的解决方案可以直接用于外部程序 (例如您的C:\Program Files\some\program.exe示例):您始终可以传递< em>值的数组 (这就是$args到外部程序,并且其元素将作为单独传递参数 (必要时进行字符串化)。

  • 如果将$args更改为@args ,则可以使用 any 命令使您的解决方案起作用 [1] < / sup>,以利用称为splatting的PowerShell参数传递技术:

function test ( [string] $option )
{
    if ( $option -eq 'A' )
    {
        Write-Host $args
    }
    elseif ( $option -eq 'B' )
    {
        # Use @args to also support passing *named* arguments
        # through to *PowerShell* commands.
        & $someCommand @args
    }
}

注意事项

  • automatic $args variable收集声明了 no 参数的所有参数,仅在 simple 中可用(非高级) )功能和脚本advanced functions and scripts-使用[CmdletBinding()]属性和/或[Parameter()]属性的对象-要求声明所有个潜在参数。

  • PowerShell具有内置的魔术,使自动 array 变量$args也支持传递 named 参数可以通过splatting 来实现,而 custom 数组或集合都不支持。

    • 相比之下,自定义数组和集合仅支持使用 positional (未命名)参数,但是,该函数涵盖了对外部程序的所有调用。
    • 在调用 PowerShell 命令时,此限制是有问题的,但是:例如,如果您想传递 named 参数{{1 }}通过使用-Path C:\声明的自定义集合参数(如OldFart's answerSet-Location)中所示,通过喷溅到ValueFromRemaining Arguments cmdlet,不会要支持通过命名参数传递(通过Set-Location @Remaining除外,如果可以的话),必须使用基于 hashtable 的外观。< / li>

因此,如果您的函数是一个高级一个 ,则需要支持将 named 参数传递给其他PowerShell命令,需要一种不同的方法this answer显示了两种选择。


[1]对于外部程序,在极端情况下@args的行为与@args不同,即$args数组包含$argsstop-parsing symbol--%识别它,@args将其视为文字。