PowerShell Looping: The Continue Statement


Summary: Microsoft Scripting Guy, Ed Wilson, talks about using the Continue statement in looping.

Microsoft Scripting Guy, Ed Wilson, is here. Dude, dude, dude (or dudette). TechEd 2014 is nearly here. Tomorrow the Scripting Wife and I jump onto a big old hairy plane and head to Houston, Texas for TechEd 2014 North America.

We will head to the Convention Center, and begin the task of assembling the Scripting Guys booth. Look for pictures and ad hoc Hey, Scripting Guy! Blog posts as I try to help you join into the virtual awesomeness that is TechEd. If you are going to be there, make sure you keep up-to-date with the Scripting Guys' guests, know where to locate the Scripting Guys booth, and even pick up a few session suggestions from the Scripting Wife’s ideal TechEd schedule. It is nearly here!

Understanding the Continue statement

One of the things that is a bit confusing for beginner scripters (and even for some intermediate scripters) is the Continue statement. This is partially because it does not act like it might in some other scripting languages.

Note  Windows PowerShell is not VBScript. Windows PowerShell is not VBScript. Say this 100 times…

So, what does the Continue statement do in Windows PowerShell? It returns flow to the top of the innermost loop that is controlled by a While, For, or Foreach statement. Probably the best way to understand this is to see it in action.

Note  To read more about looping, see these Hey, Scripting Guy! Blog posts.

The following script displays the numbers 1 through 6 as the script works its way through the array.

[array]$a = 1..6

foreach ($i in $a)

{

 $i

}

Here is the output from the script:

Image of command output

If I want to skip the number 3, I can use the If statement to see if the $i variable holds the number 3. If it does, I can use the Continue statement to return to the top of the Foreach loop, and it will continue processing. The revised script is shown here:

[array]$a = 1..6

foreach ($i in $a)

{

 If($i -eq 3){continue}

 $i

}

When I run the script, I see that, indeed, the number 3 is skipped:

Image of command output

Another example using While

I want to show another example of using Continue. This time, I will use the Get-Process cmdlet to store a collection of objects into a variable named $gps. Now I use the GetEnumerator method from the collection to create an enumerator to permit me to walk through the collection one record at a time. I use the While statement to do things while the $e.movenext() method returns True. (By the way, when the MoveNext method moves to the next record, it returns True, which makes it perfect for this example). So while my condition is True, I am going to display the current record. This is the basic script:

$gps = Get-Process

$e = $gps.GetEnumerator()

While ($e.Movenext())

{

    $e.current

}

Here is the output. Pay attention to the portion of the output that displays the Notepad process.

Image of command output

Now I add an If statement to look for the presence of the Notepad process name in the current line of the enumerator. If I find it, then I want to go back to the beginning of the While statement loop, and continue processing:

$gps = Get-Process

$e = $gps.GetEnumerator()

While ($e.Movenext())

{

    if($e.Current.name -match 'notepad'){Continue}

    $e.current

}

When I run the script, I see that the Notepad process is not present in the output:

Image of command output

That is all there is to using the Continue statement. This also concludes this series about looping. Join me tomorrow for the Weekend Scripter when we will talk about some really cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Comments (8)

  1. loads of info. thanks

  2. Jaap Brasser says:

    You probably don’t see the GetEnumerator method because this is a property of the array and not of the objects in the array. If you pipe Get-ChildItem into Get-Member the Get-Member cmdlet will receive the unpacked items in the array as input. To test this yourself have a look at the difference between the following two:
    Get-ChildItem | Get-Member
    Get-Member -InputObject (Get-ChildItem)

    For more information about this method have a look at this MSDN article: http://msdn.microsoft.com/en-us/library/system.array.getenumerator(v=vs.110).aspx

  3. alexis ragual says:

    i don’t get the getenumerator method to show in get-member. please do explain.

  4. Stacey Dillinger says:

    I see it works but when I try $e | get-member I don’t see a movenext or current in the output. Perhaps the enumerator could be a topic in a future article.

    Thank you,

    Stacey

  5. Continue vs Return in array vs hash says:

    The behavior of continue seems inconsistent. If you use "continue" while iterating an array, it works as expected (whereas "return" quits altogether). If you use "continue" while iterating a hash (via GetEnumerator), it quits, but "return" works as expected.
    WTH?…

    Example code to play with:

    # Continue = skip, return = quit
    Write-Host ‘Array’
    For ($i = 1; $i -le 10; $i++) {
    write-host $i
    If ($i -eq 5) { continue }
    #If ($i -eq 7) { return }
    write-host "—-"
    }

    write-host "Hash – GetEnumerator (Continue):"
    $h = @{a=1;b=2;c=3;d=4;e=5;f=6;g=7;h=8;i=9;j=10}
    $h.GetEnumerator() | ForEach {
    write-host $_.Value
    If ($_.Value -eq 5) { continue }
    write-host "—-"
    }

    write-host "Hash – GetEnumerator (Return):"
    $h = @{a=1;b=2;c=3;d=4;e=5;f=6;g=7;h=8;i=9;j=10}
    $h.GetEnumerator() | ForEach {
    write-host $_.Value
    If ($_.Value -eq 5) { return }
    write-host "—-"
    }

  6. thepip3r says:

    You’re slightly confusing the issue. It’s not a problem with array vs hashtable. The problem is a loop versus a scriptblock. PowerShell loops respond appropriately to continue but foreach-object which is a scriptblock responds as intended with the use
    of return.

  7. Loïc MICHEL says:

    This article is a bit misleading as continue does not work as expected with foreach-object cmdlet and return must be used in that case. I think this should be mentioned at the top of the page.

    http://stackoverflow.com/a/7763698/381149

Skip to main content