Josh Petitt
Josh Petitt

Reputation: 9579

PowerShell how to use $MyInvocation for recursion

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

Answers (2)

Dabombber
Dabombber

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

EBGreen
EBGreen

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

Related Questions