With the following script:
$ErrorActionPreference = 'Stop'
try {
qweqweqwe
}
catch {
Write-Error $_ #-ErrorAction Continue
}
finally {
Read-Host -Prompt 'Press enter to continue'
}
Read-Host -Prompt 'What'
Here is the output (notice how the "finally" is executed before the "Write-Error":
Press enter to continue:
C:\Demo.ps1 : The term 'qweqweqwe' 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 C:\Demo.ps1:7 char:3
+ Write-Error $_ #-ErrorAction Continue
+ ~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Demo.ps1
Here's the expected output when I uncomment "-ErrorAction Continue":
C:\Demo.ps1 : The term 'qweqweqwe' 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.
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Demo.ps1
Press enter to continue:
What:
I can only assume that powershell, when it sees he'll "Write-Error" and exit, starts something like "ok but before that let's execute the finally block before".
Is this behavior documented somewhere?
Maybe this section in PowerShell's try-catch-finally documentation at least hints at the behavior you describe with
PowerShell runs the finally block before the script terminates or before the current block goes out of scope.
and
A finally block runs even if you use CTRL+C to stop the script. A finally block also runs if an Exit keyword stops the script from within a catch block.
Also, the behavior you observe seems common. For example JavaScript seems to have the same behavior when I test. And the following C# example
using System;
public class Program
{
public static void Main()
{
try {
Console.WriteLine("in try block");
throw new Exception("throw in try block");
} catch {
Console.WriteLine("in catch block");
throw new Exception("throw in catch block");
} finally {
Console.WriteLine("in finally block");
}
}
}
behaves the same as PowerShell; the output is
in try block
in catch block
in finally block
Run-time exception (line 12): throw in catch block
Which aligns with the last paragraph in this section in the already referenced try-catch-finally documentation
try, catch, and finally resemble the try, catch, and finally keywords used in the C# programming language.
So maybe the documentation isn't particularly explicit because the try, catch, and finally blocks work similarly to other programming languages.