cmdlet 的包装函数 - 传递其余参数

Wrapper function for cmdlet - pass remaining parameters

我正在编写一个使用 ValueFromRemainingArguments 包装 cmdlet 的函数(如 here 所讨论)。

下面的简单代码演示了这个问题:

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 Community Extensions to no avail. At the moment I'm almost considering a bug (maybe related to this ticket??) 中解决 GetTypeEchoArgs 的问题。

高级函数最佳解决方案(使用[CmdletBinding()]属性and/or一个[Parameter()] 属性)是为了 通过 PowerShell SDK 搭建一个代理(包装器)函数,如 所示。 这实质上涉及 复制 目标命令的参数声明(虽然是自动的,但是是静态的)。

如果您不想使用这种方法,您唯一的选择是执行您自己的解析 $UnboundArgs 数组(从技术上讲,它是 [System.Collections.Generic.List[object]] 的一个实例),但是它很麻烦,而且不是万无一失的:

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'

  • 此外,与顶部提到的基于脚手架的代理函数方法不同,您不会获得任何传递参数的制表符补全,传递参数也不会被列为 -? / Get-Help / Get-Command -Syntax.

如果您不介意既没有制表符补全也没有语法帮助 and/or 您的包装函数必须支持传递给 multiple事先未知目标命令,使用简单(非高级)函数和@args (如在您的工作示例中;另见下文) 是最简单的选项,假设您的函数 本身 不需要支持 common parameters(需要高级函数)。
使用 simple 函数还意味着将公共参数传递给包装命令 only(而 advanced 函数会将它们解释为 本身 ,尽管它们的效果 usually 传播到函数内部的调用;然而,使用 -OutVariable 等公共参数,区别很重要)。


至于你试过的

虽然 PowerShell 通过 arrays(或类似数组的集合,例如 [System.Collections.Generic.List[object]])支持 splatting原则上,如果所有元素都作为 positional arguments and/or 如果目标命令是 external,则此 仅按预期工作program(PowerShell 对其参数结构一无所知,并且始终将参数作为 list/array 个标记传递)。

为了将带有 命名参数 的参数传递给其他 PowerShell 命令,您必须使用基于 hashtable 的展开,其中每个条目的键标识目标 参数,值标识参数 value(参数)。

尽管 automatic $args variable 在技术上也是一个 数组 ([object[]]),PowerShell 具有 内置-在 magic 中允许使用 @args 进行拼接也可以使用命名参数 - 这 not 可以使用任何自定义数组或集合。

请注意自动 $args 变量,它收集声明了 no 参数的所有参数 - 是 仅在简单(非高级)函数和脚本中可用advanced functions and scripts - 使用 [CmdletBinding()] 属性的那些 and/or [Parameter()] 属性 - 要求声明 所有 个潜在参数。