Я ' m пытается написать некоторые функции PowerShell, которые делают что-то, а затем прозрачно вызывают существующие встроенные функции. Я хочу передать все аргументы нетронутыми. Я не хочу знать никаких подробностей аргументов.
Я устал использовать 'splat' для этого с @args
, но это не сработало, как я ожидал.
В В приведенном ниже примере я написал игрушечную функцию с именем myls
, которая должна была печатать hello! , а затем вызывать ту же встроенную функцию 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
...
Вуаля! Эта новая версия прошла все испытания.