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

Tho*_*ten 1 parameters powershell wrapper

我正在编写一个使用 ValueFromRemainingArguments 包装 cmdlet 的函数(如此处所述

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

  • 作品
function Test-WrapperArgs {
    Set-Location @args
}
Run Code Online (Sandbox Code Playgroud)
Test-WrapperArgs -Path C:\ 
Run Code Online (Sandbox Code Playgroud)
  • 不起作用
Test-WrapperArgs -Path C:\ 
Run Code Online (Sandbox Code Playgroud)
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:\'.
Run Code Online (Sandbox Code Playgroud)

我尝试通过 PowerShell 社区扩展来解决该问题,GetTypeEchoArgs没有成功。目前我几乎正在考虑一个错误(可能与这张票有关??)。

mkl*_*nt0 5

高级函数(使用属性和/或属性的函数)的最佳解决方案是通过PowerShell SDK 构建代理(包装器)函数,如本答案所示。这本质上涉及复制目标命令的参数声明(尽管以自动但静态的方式)。[CmdletBinding()][Parameter()]

如果您不想使用这种方法,您唯一的选择是执行您自己的数组解析$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

}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 这并不是万无一失的,因为您的函数将无法区分实际参数名称(例如,-Path)和恰好看起来像参数名称的字符串文字(例如,'-Path'

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

如果您不介意既没有制表符完成也没有语法帮助和/或您的包装函数必须支持传递到多个预先未知的目标命令,请使用一个简单的(非高级)函数@args(如在您的工作示例中;另见下文)是最简单的选项,假设您的函数本身不需要支持通用参数(这需要高级函数)。
使用简单函数还意味着公共参数传递给包装的命令(而高级函数会将它们解释为本身的意思,尽管它们的效果通常传播到函数内部的调用;但是-OutVariable,使用公共参数,例如区别很重要)。


至于你尝试过的

虽然PowerShell[System.Collections.Generic.List[object]]原则上确实支持通过数组(或类似数组的集合,例如)进行展开,但只有当所有元素都作为位置参数传递和/或目标命令是外部程序(关于其参数结构)时,这才按预期工作。 PowerShell 一无所知,并且始终将参数作为标记列表/数组传递)。

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

尽管自动$args变量在技术上也是一个数组( [object[]]),但 PowerShell 具有内置的魔法,允许 splatting with@args也可以使用命名参数- 这不适用于任何自定义数组或集合。

请注意,自动$args变量收集声明参数的所有参数 -仅在简单(非高级)函数和脚本中可用;高级函数和脚本- 使用[CmdletBinding()]属性和/或 属性的函数[Parameter()]和脚本 - 要求声明所有潜在参数。