Используя Powershell introspection, чтобы найти имя функции, переданной в качестве параметра? - PullRequest
0 голосов
/ 05 ноября 2018

Скажите, я передаю функцию в качестве параметра , есть ли способ узнать имя переданной функции посредством самоанализа в powershell? Или мне просто нужно передать его вместе с остальными параметрами?

(без вызова рассматриваемой функции)

1 Ответ

0 голосов
/ 05 ноября 2018

Связанный вопрос пытается передать функцию по name в виде string , и в этом случае ответ очевиден: сам аргумент является именем функции.

В случае, если вместо этого передан блок сценария , вы можете использовать следующую технику:

function get-ScriptBlockCommandName {

  param(
   [scriptblock] $ScriptBlock,
   [switch] $Expand 
  )

  # Using the script block's AST, extract the first command name / path token.
  $commandName = $ScriptBlock.Ast.EndBlock.
    Statements[0].PipelineElements.CommandElements[0].Extent.Text

  # Expand (interpolate) the raw name, if requested.
  if ($Expand) {
    $commandName = $ExecutionContext.InvokeCommand.ExpandString($commandName) 
  }

  # Remove outer quoting, if present.
  if ($commandName -match '^([''"])(.+)\1$') {
    $commandName = $Matches[2]
    if ($Matches[1] -eq "'") { $commandName = $commandName -replace "''", "'" }
  } 

  # Output
  $commandName

}

Функция возвращает (первое) имя команды / путь, который вызывается из блока скрипта.

Предостережения

  • Произойдет ошибка, если вы передадите выражение (например, 1 + 2) в качестве первого оператора внутри блока скрипта.

  • Анализируется только команда first (и возвращается имя / путь ее команды), в то время как количество операторов, которые можно поместить в блок скрипта, не ограничено.

  • По умолчанию, если имя / путь команды составлено из переменных / других команд, они не раскрываются (интерполируются), учитывая, что это может привести к выполнению команд; чтобы выбрать расширение, используйте переключатель -Expand.

Пример звонков:

PS> get-ScriptBlockCommandName { foo -bar baz -more stuff }
foo

Это также работает с указанными именами / путями (обратите внимание, как тогда & необходимо использовать для вызова команды):

PS> get-ScriptBlockCommandName { & '/dir name/foo' -bar baz -more stuff }
/dir name/foo

Однако, чтобы избежать потенциально нежелательного выполнения команд, имя / путь команды возвращается как есть , со ссылками на переменные и подвыражениями нерасширенными .
Вы можете выбрать их расширение, передав -Expand:

PS> get-ScriptBlockCommandName { & "$HOME/scripts/foo.ps1" -bar baz  } -Expand
C:/Users/jdoe/scripts.ps1  # e.g.
...