我正在尝试编写一些PowerShell函数来执行某些操作,然后透明地调用现有的内置函数。我想传递所有未被触及的论点。我不想知道论点的任何细节。
我厌倦了使用'splat'来做到这一点 @args
但这并没有像我预期的那样奏效。
在下面的例子中,我写了一个名为的玩具函数 myls
应该打印 你好! 然后调用相同的内置函数, Get-ChildItem
,即内置别名 ls
调用其余参数行完整。到目前为止我的工作得很好:
function myls
{
Write-Output "hello!"
# $MyInvocation | Format-List # <-- uncomment this line for debug info
Invoke-Expression ("Get-ChildItem " + $MyInvocation.UnboundArguments -join " ")
}
一个正确的版本 myls
应该能够处理没有参数的调用,带有一个带有命名参数的参数,来自包含多个分号分隔命令的行,并且参数中的变量包括包含空格的字符串变量。基本上,它应该是替代品 ls
。
以下测试进行比较 myls
和内置的 ls
:
[注意:输出省略和/或压缩以节省空间]
PS> md C:\p\d\x, C:\p\d\y, C:\p\d\"jay z"
PS> cd C:\p\d
PS> ls # no args
PS> myls # pass
PS> cd ..
PS> ls d # one arg
PS> myls d # pass
PS> $a="A"; $z="Z"; $y="y"; $jz="jay z"
PS> $a; ls d; $z # multiple statements
PS> $a; myls d; $z # pass
PS> $a; ls d -Exclude x; $z # named args
PS> $a; myls d -Exclude x; $z # pass
PS> $a; ls d -Exclude $y; $z # variables in arg-line
PS> $a; myls d -Exclude $y; $z # pass
PS> $a; ls d -Exclude $jz; $z # variables containing spaces in arg-line
PS> $a; myls d -Exclude $jz; $z # FAIL!
有没有办法可以重写 myls
得到我想要的行为?
简短回答: 是的,这是可能的。坏消息:它需要代码知道参数的细节以及有关希望调用的函数的其他元数据。好消息: 一个人不需要自己写这个。这个元数据以编程方式可用,并且存在可用的模块,可用于自动生成骨架代理代码(请参阅下面的@ Jaykul的答案)。我选择使用 名为“MetaProgramming”的模块。导入后,生成一个插件 myls
脚本很简单:
New-ProxyCommand ls > .\myls.ps1
然后可以开始自定义新生成的 myls.ps1
脚本,像这样:
...
begin
{
Write-Output "hello!" # <-- add this line
try {
$outBuffer = $null
...
瞧!这个新版本通过了所有测试。