Reputation: 9579
I am trying to implement some recursive functions with PowerShell. Here is the basic function:
function MyRecursiveFunction {
param(
[parameter(Mandatory=$true,ValueFromPipeline=$true)]
$input
)
if ($input -is [System.Array] -And $input.Length -eq 1) {
$input = $input[0]
}
if ($input -is [System.Array]) {
ForEach ($i in $input) {
$i | ##### HOW DO I USE $MyInvocation HERE TO CALL MyRecursiveFunction??? #####
}
return
}
# Do something with the single object...
}
I have looked at Invoke-Expression and Invoke-Item but have not been able to get the syntax right. For instance I tried
$i | Invoke-Expression $MyInvocation.MyCommand.Name
I'm guessing there is an easy way to do this if you know the right syntax :-)
Upvotes: 1
Views: 706
Reputation: 466
A bit of an old question, but since there's no satisfactory answer and I've had the same question, here's my experience.
Calling the function by name will break if the name is changed, or if the function is out of scope. It's also not very nice to manage as changing the function name requires editing all the recursive calls, and it'll likely break in modules imported using the prefix option.
# A simple recursive countdown function
function countdown {
param([int]$count)
$count
if ($count -gt 0) { countdown ($count - 1) }
}
# And a way to break it
$foo = ${function:countdown}
function countdown { 'failed' }
& $foo 5
$MyInvocation.InvocationName
is slightly nicer to work with, but will still break in the above example (although for different reasons).
The best way would seem to be calling the scriptblock of the function, $MyInvocation.MyCommand.ScriptBlock
. That way it'll still work regardless of the function name/scope.
function countdown {
param([int]$count)
$count
if ($count -gt 0) { & $MyInvocation.MyCommand.ScriptBlock ($count - 1) }
}
Upvotes: 2
Reputation: 37740
Just Call the function:
$i | MyRecursiveFunction
To call it without knowing the name of the function you should be able to call it with $myInvocation.InvocationName:
Invoke-Expression "$i | $($myInvocation.InvocationName)"
Upvotes: 0