2

When piping the output of a command to a ForEach-Object loop in PowerShell, using a continue statement causes it to error out.

Works as expected:

ipconfig | ForEach-Object {
  $_
} 

Errors:

ipconfig | ForEach-Object {
  $_
  continue
} 

The error is

Program 'ipconfig.exe' failed to run: System error.At C:\Users\test\ps.ps1:1 char:1
+ nslookup google.com | ForEach-Object {
+ ~~~~~~~~~~~~~~~~~~~.
At C:\Users\test\ps.ps1:1 char:1
+ nslookup google.com | ForEach-Object {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [], ApplicationFailedException
    + FullyQualifiedErrorId : NativeCommandFailed

This seems to happen with any external command, such as nslookup and net

I thought maybe this had to do with some type conversion, but the object inside the loop is always a string. Saving the command output to a variable, and then doing a $var | ForEach-Object works.

2
  • What's the point of using continue as the very last statement in the block? Commented Mar 20, 2024 at 16:23
  • 2
    There is no point, but it's to keep the minimal reproducible example short and easy Commented Mar 20, 2024 at 17:17

1 Answer 1

3

continue statements in PowerShell can only be used within loop constructs. While ForEach-Object seems like a loop, it's not.

In PowerShell, you can technically use continue outside of a loop, but it causes PowerShell to not find a loop, and just terminate the current runspace.1

This means PowerShell can actually terminate the caller1, and looking at the callstack, that caller is the "parent" line and so it is terminated.

Callstack right before the continue executes:

ScriptLineNumber : 4
Position         : continue
FunctionName     : <ScriptBlock>


ScriptLineNumber : 1
Position         : net help | ForEach-Object {
                       $_.GetType()
                       continue
                   }
FunctionName     : <ScriptBlock>

Instead, use a return statement.


Reference

1 - https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_continue?view=powershell-5.1

Sign up to request clarification or add additional context in comments.

2 Comments

Nice; worth nothing that the same applies analogously to break
More specifically: When break or continue are used in a statement that isn't loop-like (doesn't itself support these keywords), PowerShell walks up the call stack to find a loop, and breaks out of / continues the first one found (which may be unrelated to what you're trying to do). Only if no loop is found anywhere on the call stack is the runspace quietly exited. E.g., do { 1..10 | ForEach-Object { if ($_ -gt 5) { break }; $_ } } while ($false) causes the break to exit the enclosing do loop, a technique that can be leveraged to exit a pipeline prematurely.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.