Я пытаюсь написать некоторые функции 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" . После импортирования создание drop-in myls
script мертво просто:
New-ProxyCommand ls > .\myls.ps1
Затем можно начать настройку вновь созданного myls.ps1
script, например:
...
begin
{
Write-Output "hello!" # <-- add this line
try {
$outBuffer = $null
...
Voila! Эта новая версия проходит все тесты.