将一组未指定的参数传递给函数并传递给cmdlet

时间:2014-07-27 19:00:54

标签: powershell

假设我想写一个包装Read-Host的辅助函数。此函数将通过更改提示颜色,调用读取主机,然后更改颜色来增强读取主机(简单示例用于说明目的 - 实际上并未尝试解决此问题)。

由于这是Read-Host的包装器,我不想在函数头中重复Read-Host的所有参数(即Prompt和AsSecureString)。有没有办法让函数获取一组未指定的参数,然后将这些参数直接传递给函数中的cmdlet调用?我不确定Powershell是否有这样的设施。

例如......

function MyFunc( [string] $MyFuncParam1, [int] $MyFuncParam2 , Some Thing Here For Cmdlet Params that I want to pass to Cmdlet )
{    
    # ...Do some work...
    Read-Host Passthru Parameters Here
    # ...Do some work...

}

2 个答案:

答案 0 :(得分:9)

听起来你对#ValueFromRemainingArguments'感兴趣?参数属性。要使用它,您需要创建一个高级功能。有关详细信息,请参阅about_Functions_Advanced和about_Functions_Advanced_Parameters帮助主题。

使用该属性时,任何额外的未绑定参数都将分配给该参数。我不认为它们可以原样使用,所以我做了一个小功能来解析它们(见下文)。解析它们之后,返回两个变量:一个用于任何未命名的位置参数,另一个用于命名参数。然后可以将这两个变量splat到您要运行的命令。这是可以解析参数的辅助函数:

function ParseExtraParameters {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromRemainingArguments=$true)]
        $ExtraParameters
    )

    $ParamHashTable = @{}
    $UnnamedParams = @()
    $CurrentParamName = $null
    $ExtraParameters | ForEach-Object -Process {
        if ($_ -match "^-") {
            # Parameter names start with '-'
            if ($CurrentParamName) {
                # Have a param name w/o a value; assume it's a switch
                # If a value had been found, $CurrentParamName would have
                # been nulled out again
                $ParamHashTable.$CurrentParamName = $true
            }

            $CurrentParamName = $_ -replace "^-|:$"
        }
        else {
            # Parameter value
            if ($CurrentParamName) {
                $ParamHashTable.$CurrentParamName += $_
                $CurrentParamName = $null
            }
            else {
                $UnnamedParams += $_
            }
        }
    } -End {
        if ($CurrentParamName) {
            $ParamHashTable.$CurrentParamName = $true
        }
    }

    ,$UnnamedParams
    $ParamHashTable
}

您可以像这样使用它:

PS C:\> ParseExtraParameters -NamedParam1 1,2,3 -switchparam -switchparam2:$false UnnamedParam1

UnnamedParam1

Name                           Value                                                                                                                                                 
----                           -----                                                                                                                                                 
switchparam                    True                                                                                                                                                  
switchparam2                   False                                                                                                                                                 
NamedParam1                    {1, 2, 3}                                                                                                                                             

这里有两个可以使用辅助函数的函数(一个是你的例子):

function MyFunc {
    [CmdletBinding()]
    param(
        [string] $MyFuncParam1, 
        [int] $MyFuncParam2,
        [Parameter(Position=0, ValueFromRemainingArguments=$true)]
        $ExtraParameters
    )
    # ...Do some work...
    $UnnamedParams, $NamedParams = ParseExtraParameters @ExtraParameters
    Read-Host @UnnamedParams @NamedParams
    # ...Do some work...
}

function Invoke-Something {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true, Position=0)]
        [string] $CommandName,
        [Parameter(ValueFromRemainingArguments=$true)]
        $ExtraParameters
    )

    $UnnamedParameters, $NamedParameters = ParseExtraParameters @ExtraParameters
    &$CommandName @UnnamedParameters @NamedParameters
}

导入所有三个功能后,请尝试以下命令:

MyFunc -MyFuncParam1 Param1Here "PromptText" -assecure
Invoke-Something -CommandName Write-Host -Fore Green "Some text" -Back Red

答案 1 :(得分:4)

一个字:splatting。

更多的话:您可以使用$PSBoundParameters和splatting的组合将参数从外部命令传递到内部命令(假设名称匹配)。您需要首先从$PSBoundParameters删除您不想使用的任何参数:

$PSBoundParameters.Remove('MyFuncParam1')
$PSBoundParameters.Remove('MyFuncParam2')
Read-Host @PSBoundParameters

修改

示例函数体:

function Read-Data {
param (
    [string]$First,
    [string]$Second,
    [string]$Prompt,
    [switch]$AsSecureString
)

    $PSBoundParameters.Remove('First') | Out-Null
    $PSBoundParameters.Remove('Second') | Out-Null
    $Result = Read-Host @PSBoundParameters
    "First: $First Second: $Second Result: $Result"
}

Read-Data -First Test -Prompt This-is-my-prompt-for-read-host