Say I'm passing a function as a parameter , is there a way to find out the name of the passed function through introspection in powershell? Or do I just have to pass it along with the rest of the parameters?
(without calling the function in question)
The linked question tries to pass a function by name , as a string , in which case the answer is obvious: the argument itself is the function name.
In case a script block is passed instead, you can use the following technique:
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
}
The function returns the (first) command name / path that is called from inside the script block.
Caveats :
An error will occur if you pass an expression (eg, 1 + 2
) as the first statement inside the script block.
Only the first command is analyzed (and its command name / path returned), whereas there is no limit to how many statements you can place inside a script block.
By default, if the command name / path is constructed from variables / other commands, these are not expanded (interpolated), given that doing so can result in execution of commands; to opt into expansion, use the -Expand
switch.
Example calls:
PS> get-ScriptBlockCommandName { foo -bar baz -more stuff }
foo
This also works with quoted names / paths (note how &
must then be used to invoke the command):
PS> get-ScriptBlockCommandName { & '/dir name/foo' -bar baz -more stuff }
/dir name/foo
However, to avoid potentially unwanted execution of commands, the command name / path is returned as-is , with variable references and subexpressions unexpanded .
You can opt to have these expanded by passing -Expand
:
PS> get-ScriptBlockCommandName { & "$HOME/scripts/foo.ps1" -bar baz } -Expand
C:/Users/jdoe/scripts.ps1 # e.g.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.