Resursion

Tagged: 

This topic contains 5 replies, has 4 voices, and was last updated by Profile photo of Brian Cyr Brian Cyr 1 year, 11 months ago.

  • Author
    Posts
  • #21504
    Profile photo of Brian Cyr
    Brian Cyr
    Participant

    I have a question about calling a function recursively.
    I have a function that has two parameter sets. If the user chooses one of the sets, I want to perform a short operation and then call my routine again but this time using the other parameter set. Like so

    Function DoThis[]
    {
        [CmdletBinding[SupportsShouldProcess=$true, ConfirmImpact='Low']]
        [OutputType[[String[]]]]
        Param[
            [Parameter[Mandatory=$True,ParameterSetName="ByIP"]][String[]]$IP,
            [Parameter[Mandatory=$True,ParameterSetName="ByHost"]][String[]]$HostName
            ]
        If [$PSCmdlet.ParameterSetName -eq "ByHost"] 
        {
            Foreach[$ThisHost in $HostName]
            {
                $ThisIP = Convert-HostNameToIP[$ThisHost]
                DoThis -IP $ThisIP
            }
        } else {
    
            If [$PSCmdlet.ShouldProcess[$IP,"Some operation"]] {
                #Do some stuff with this IP address
            }
        }
    }

    If the function is called DoThis -HostName "BlahBlah" -WhatIf then will the recursive call also have the -WhatIf property set? If not, how do I pass it? Can I pass the $PSCmdlet object and will Powershell handle that?

  • #21506
    Profile photo of Tim Pringle
    Tim Pringle
    Participant

    Personally speaking, I wouldn't use this method at all, think it's over complicating things. If you're providing a cmdlet that provided two forms of possible input, then the cmdlet shouldnt need to call itself for it to operate as required.

    Why not just create an array called $IP if hostnames are provided, and then within a ForEach, get the IP address for each host and add it to the array $IP array? Then when finished, proceed with the #do some stuff part.

  • #21511
    Profile photo of Matt McNabb
    Matt McNabb
    Participant

    To add to what Tim said, I would question even using the parameter sets. Most native cmdlets with a -ComputerName parameter will accept either a host name or an IP address. Is there any particular reason this can't be done?

    Also, if you are using Powershell 4.0, you can just use Resolve-DnsName instead of using a custom function as you have done. Of course it's understandable if you don't have access to version 4.0 for some reason.

  • #21522
    Profile photo of Brian Cyr
    Brian Cyr
    Participant

    The example I posted was an overly simplified example and really has nothing to do with what I am trying to accomplish other than that is has recursion in it.

    My question is, if I call a function with -WhatIf, -Confirm or -Verbose and this function is recursive. How do I pass along the fact that these switches were set in the parent call? Do child calls inherit these switches? Do I need to pass $PSCmdlet?

  • #21523
    Profile photo of Daniel Krebs
    Daniel Krebs
    Participant

    Brian,

    I agree with Tim and Matt that there is most likely a simpler way to do this. To answer your questions. You can use the automatic variable $PSBoundParameters, remove the HostName parameter and splat it to your next invocation of DoThis with the IP parameter. This will keep your WhatIf, Confirm and Verbose switches. Verbose is actually kind of recursive depending on where you use the -Verbose switch (at the function or script invocation level).

    Example for $PSBoundParameters:

    function DoThis {
    
        [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Low')]
        [OutputType([String[]])]
        
        Param(
    
            [Parameter(Mandatory=$True,ParameterSetName="ByIP")]
            [String[]]
            $IP,
    
            [Parameter(Mandatory=$True,ParameterSetName="ByHost")]
            [String[]]
            $HostName
        )
        
        if ($PSCmdlet.ParameterSetName -eq "ByHost") {
    
            foreach ($ThisHost in $HostName) {
    
                $ThisIP = Convert-HostNameToIP($ThisHost)
    
                $PSBoundParameters.Remove('HostName')
    
                DoThis -IP $ThisIP @PSBoundParameters
            }
        } else {
     
            if ($PSCmdlet.ShouldProcess($IP,"Some operation")) {
                "Do some stuff with this IP address $IP"
            }
        }
    }
    

    Best,
    Daniel

  • #21657
    Profile photo of Brian Cyr
    Brian Cyr
    Participant

    Daniel,
    Thank you for the information on @PSBoundParameters. That is [u][b]exactly[/b][/u] what I was looking for.

    It's still funny to me how I keep hearing that all variables should be singular and yet I still see some internal variables as plural.

You must be logged in to reply to this topic.