cmdlet的包装器功能-传递其余参数 [英] Wrapper function for cmdlet - pass remaining parameters
问题描述
我正在编写一个使用ValueFromRemainingArguments封装cmdlet的函数(如所讨论的这里).
I'm writing a function that wraps a cmdlet using ValueFromRemainingArguments (as discussed here).
以下简单代码演示了该问题:
The following simple code demonstrates the problem:
- 有效
function Test-WrapperArgs {
Set-Location @args
}
Test-WrapperArgs -Path C:\
- 不起作用
function Test-WrapperUnbound {
Param(
[Parameter(ValueFromRemainingArguments)] $UnboundArgs
)
Set-Location @UnboundArgs
}
Test-WrapperUnbound -Path C:\
Set-Location: F:\cygwin\home\thorsten\.config\powershell\test.ps1:69
Line |
69 | Set-Location @UnboundArgs
| ~~~~~~~~~~~~~~~~~~~~~~~~~
| A positional parameter cannot be found that accepts argument 'C:\'.
我尝试通过 PowerShell社区扩展解决GetType
和EchoArgs
问题无济于事.目前,我几乎要考虑一个错误(可能与此票证有关??? ).
I tried getting to the issue with GetType
and EchoArgs
from the PowerShell Community Extensions to no avail. At the moment I'm almost considering a bug (maybe related to this ticket??).
推荐答案
最好的解决方案是通过PowerShell SDK 搭建代理(包装器)功能,如
The best solution is to scaffold a proxy (wrapper) function via the PowerShell SDK, as shown in this answer. This involves essentially duplicating the target command's parameter declarations (albeit in an automatic, but static fashion).
如果您不想使用此方法,则唯一的选择是对$UnboundArgs
数组进行自己的解析(从技术上讲,它是[System.Collections.Generic.List[object]]
),但是很麻烦,而且不是万无一失的:
If you do not want to use this approach, your only option is to perform your own parsing of the $UnboundArgs
array (technically, it is an instance of [System.Collections.Generic.List[object]]
), which is cumbersome, however, and not foolproof:
function Test-WrapperUnbound {
Param(
[Parameter(ValueFromRemainingArguments)] $UnboundArgs
)
# (Incompletely) emulate PowerShell's own argument parsing by
# building a hashtable of parameter-argument pairs to pass through
# to Set-Location via splatting.
$htPassThruArgs = @{}; $key = $null
switch -regex ($UnboundArgs) {
'^-(.+)' { if ($key) { $htPassThruArgs[$key] = $true } $key = $Matches[1] }
default { $htPassThruArgs[$key] = $_; $key = $null }
}
if ($key) { $htPassThruArgs[$key] = $true } # trailing switch param.
# Pass the resulting hashtable via splatting.
Set-Location @htPassThruArgs
}
注意:
-
这并不是万无一失的,因为您的函数将无法区分实际的参数名称(例如
-Path
)和恰好看起来像参数名称的字符串文字(例如'-Path'
)
This isn't foolproof in that your function won't be able to distinguish between an actual parameter name (e.g.,
-Path
) and a string literal that happens to look like a parameter name (e.g.,'-Path'
)
此外,与顶部提到的基于脚手架的代理功能方法不同,任何传递参数都不会完成制表符补全,并且传递参数不会与-?
/Get-Help
/Get-Command -Syntax
.
Also, unlike with the scaffolding-based proxy-function approach mentioned at the top, you won't get tab-completion for any pass-through parameters and the pass-through parameters won't be listed with -?
/ Get-Help
/ Get-Command -Syntax
.
如果您不介意既不使用制表符完成也不使用语法帮助,并且/或者包装函数必须支持传递到 multiple 或 unknown-in- 目标命令,将简单(非高级)功能与@args
一起使用(如您的工作示例;另请参见下文),是最简单的选项,假设您的功能本身不是 ,则需要支持 通常 传播到函数内部的调用;使用通用参数(例如-OutVariable
,但是区别很重要).
If you don't mind having neither tab-completion nor syntax help and/or your wrapper function must support pass-through to multiple or not-known-in-advance target commands, using a simple (non-advanced) function with @args
(as in your working example; see also below) is the simplest option, assuming your function doesn't itself need to support common parameters (which requires an advanced function).
Using a simple function also implies that common parameters are passed through to the wrapped command only (whereas an advanced function would interpret them as meant for itself, though their effect usually propagates to calls inside the function; with a common parameter such as -OutVariable
, however, the distinction matters).
关于您尝试过的事情:
虽然 PowerShell确实支持原则上通过 arrays (或类似数组的集合,例如[System.Collections.Generic.List[object]]
)喷溅,该仅在所有元素都将作为 positional 参数和/或如果目标命令是外部程序 (关于PowerShell的参数结构,它一无所知,并且始终将参数作为令牌的列表/数组传递) ).
While PowerShell does support splatting via arrays (or array-like collections such as [System.Collections.Generic.List[object]]
) in principle, this only works as intended if all elements are to be passed as positional arguments and/or if the target command is an external program (about whose parameter structure PowerShell knows nothing, and always passes arguments as a list/array of tokens).
为了将带有命名参数的参数传递给其他PowerShell命令,必须使用基于 hashtable 的splatting ,其中每个条目的键都标识目标参数和值参数 value (参数).
In order to pass arguments with named parameters to other PowerShell commands, you must use hashtable-based splatting, where each entry's key identifies the target parameter and the value the parameter value (argument).
即使自动$args
变量从技术上讲也是一个数组([object[]]
), PowerShell具有内置魔术,允许使用@args
进行拼写使用命名参数-不适用于任何自定义数组或集合.
Even though the automatic $args
variable is technically also an array ([object[]]
), PowerShell has built-in magic that allows splatting with @args
to also work with named parameters - this does not work with any custom array or collection.
请注意,自动$args
变量将收集声明了 no 参数的所有参数-仅在 simple (非高级)函数和脚本中可用; 高级函数和脚本-使用[CmdletBinding()]
属性和/或[Parameter()]
属性的脚本-要求声明所有个潜在参数.
Note that the automatic $args
variable, which collects all arguments for which no parameter was declared - is only available in simple (non-advanced) functions and scripts; advanced functions and scripts - those that use the [CmdletBinding()]
attribute and/or [Parameter()]
attributes - require that all potential parameters be declared.
这篇关于cmdlet的包装器功能-传递其余参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!