3

I have a function that I know will throw an error. This error is expected, but when it's thrown I want to end the function. I have a Trap section in my script, and I have used both the Return and the Break commands, but they don't do what I want. I have the trap statement both in the Begin {} and the Process {} sections. I am using the command Get-WmiObject, and I have the -ErrorAction set to stop. A sample of the code and their responses are below.

First Example w/ return:

Function Test {
Param {"Some Parameters"}
Begin {"Some beginning stuff"}
process {
    Trap
    {
        Add-Content $($SomeFile) $($ComputerName + "is Not There")
        return
    } #End Trap
    Get-WmiObject Win32_NTLogEvent `
        -ComputerName $ComputerName `
        -Credential $Cred - `
        -ErrorAction Stop
    }#End Process
End {"Some ending things"}
} #End Function

This one simply keeps going on, without exiting the function.

Second Example w/ break:

Function Test {
Param {"Some Parameters"}
Begin {"Some beginning stuff"}
process {
    Trap
    {
        Add-Content $($SomeFile) $($ComputerName + "is Not There")
        Break
    } #End Trap
    Get-WmiObject Win32_NTLogEvent `
        -ComputerName $ComputerName `
        -Credential $Cred - `
        -ErrorAction Stop
    }#End Process
End {"Some ending things"}
} #End Function

This one exits the entire script.

I have looked around, but I can't find anything specific to exiting just a function. There is a lot more going on in the function, including another Get-WmiObject command. I want it to exit the function if the first Get-WmiObject can't contact the computer. I can't use a ping test, because many of the servers block ICMP.

Nick
  • 256
  • 1
  • 5
  • 20

3 Answers3

3

The $?varible can be good for catching errors. It contains a boolean for the last executed command. If the command was excuted without errors $? = $true. The $? will be $false when the last executed command errored.

Create a boolean that gets set each time after the command that errors. Assuming that the command here is get-wmiObject:

$running = $true
While ($running) {
Get-WmiObject Win32_NTLogEvent -ComputerName $ComputerName -Credential $Cred
$running = $?
}

Since you probably have a conditional in your loop already, it would look something like while(<condition> -and $running)

And if you would like to add your error message in, just throw something after you set running like this

if(!$running){Add-Content $($SomeFile) $($ComputerName + "is Not There")  }
Cole9350
  • 145
  • 4
  • I updated the main post. This would prevent the second command from running, but I want the entire function to stop, not just prevent the next command(s). – Nick Jul 23 '12 at 21:07
  • I understand what you are trying to do, but I do not believe powershell has an equivalent for the return statement you may be use to in other coding languages. In powershell, everything that is not captured in a function is then returned. So I believe the only way to actually "return" is to get to the bottom of your function. You can do this in a couple of different of ways, you just have to go with a different route that your currently attempting. You can throw all of that `End {"Some ending things"}` in an if statement that checks if there was an error. Seperate into 2 functions for tidiness – Cole9350 Jul 24 '12 at 13:43
  • Ok, since there is no easy way to exit the function in Powershell, what I ended up doing was in the begin {} block was assign a variable to the value of $?. I used an If {} Else {} statement rather then while {}, but in the end this was the comment that gave the correct answer. – Nick Jul 24 '12 at 16:21
3

Return will in fact not help, but you can use break, the only requirement is to use it as it was designed - to get out of the loop... :)

Trick here is to build simple loop that will run only once no matter what and use break inside the loop:

# Script body...

do {
    Test-WithBreak
} until ($true)

# Other operations you want to perform even if Test-WithBreak breaks.

The reason behind it is the fact, that break is loop directive and in PowerShell it does not care for any limits (so break in script, run from script, run from script will be able to walk all the way up and kill whole thing, unless it find some loop to stop him).

I blogged about this issue a while ago.

BartekB
  • 666
  • 6
  • 9
  • I have wrapped my function call in a Do {} Until loop, but the break is still stopping the whole script. I ended up using the idea @cole9350 had. I assigned $? to a variable and in the process block I check it before running any of the script. I just testing it and everything is working. – Nick Jul 24 '12 at 16:19
2

Try "Continue" as keyword

Trap [Exception] { “In PowerShell” }

MichelZ
  • 11,008
  • 4
  • 30
  • 58