Home > OS >  Powershell CommandNotFoundException is terminating?
Powershell CommandNotFoundException is terminating?

Time:09-22

When executing such a script:

nonexistingcommand
echo "Hello"

I get:

nonexistingcommand : The term 'nonexistingcommand' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the 
name, or if a path was included, verify that the path is correct and try again.
At D:\Playground\powershell\Test.ps1:2 char:1
  nonexistingcommand
  ~~~~~~~~~~~~~~~~~~
      CategoryInfo          : ObjectNotFound: (nonexistingcommand:String) [], CommandNotFoundException
      FullyQualifiedErrorId : CommandNotFoundException
 
Hello

So it seems that the CommandNotFoundException is a non-terminating error. So why if I

try {
 nonexistingcommand
}
catch [System.Management.Automation.CommandNotFoundException] {
  throw
}
echo "Hello"

In this case, it will exit and not print "Hello".

Why is that?

CodePudding user response:

Unfortunately, PowerShell has two types of terminating errors:

  • Statement-terminating errors, which by default only terminate the enclosing statement.

    • By default, execution resumes, namely with the next statement (echo "Hello" in your case)

    • CommandNotFoundException is an instance of such an error.

    • By contrast, non-terminating errors continue processing even of the enclosing statement, if further pipeline input is available.

  • Script-terminating (thread-terminating) errors, which terminate the enclosing script and the entire call stack.

    • Such errors are triggered by the throw statement called from PowerShell code, never by binary (compiled) cmdlets.

The try { ... } catch { ... } finally { ... } statement does not distinguish between these two subtypes: it catches them both.

  • Given that your catch block contains an argument-less throw statement, which implicitly relays the error that triggering error, you're effectively turning the statement-terminating error into a script-terminating one, so execution ends there.

Similarly, setting the $ErrorActionPreference preference variable to 'Stop' causes all types of errors (emitted by PowerShell commands[1]), including non-terminating ones, to abort execution overall; in other words: both non-terminating and statement-terminating errors are promoted to script-terminating ones.


For a comprehensive overview of PowerShell's surprisingly complex error handling, see GitHub docs issue #1583.


[1] At least in local, foreground invocations of external programs in consoles (terminals), stderr output is by default not routed via PowerShell's error stream, and therefore not affected by $ErrorActionPreference.

CodePudding user response:

The above error that states command was not found is a terminating error. When such an error is encountered, powershell pipeline stops execution. Only the statements within catch block are executed.

To know the difference between terminating and non-terminating errors, checkout this link: https://www.tutorialspoint.com/what-is-terminating-and-non-terminating-errors-in-powershell

If some statements are to be executed even if you encounter a terminating error, specify them within finally:

try {
 nonexistingcommand
}
catch [System.Management.Automation.CommandNotFoundException] {
  throw
}
finally {
  echo "Hello"
}

The above will print Hello

  • Related