假设我想写一个包装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...
}
答案 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