Как передать «строку аргумента» одной функции PowerShell другой?

Я ' 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
  ...

Вуаля! Эта новая версия прошла все испытания.

12
задан jwfearn 18 January 2011 в 03:41
поделиться