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.
- Such errors are triggered by the
The try { ... } catch { ... } finally { ... }
statement does not distinguish between these two subtypes: it catches them both.
- Given that your
catch
block contains an argument-lessthrow
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