Skip to content

Instantly share code, notes, and snippets.

@chrisoldwood
Last active July 22, 2024 04:12
Show Gist options
  • Save chrisoldwood/bbd6aac19bac2ff0c54ba32a705c939b to your computer and use it in GitHub Desktop.
Save chrisoldwood/bbd6aac19bac2ff0c54ba32a705c939b to your computer and use it in GitHub Desktop.
A set of tests to show if your version of PowerShell returns the correct exit code under various error conditions.
param(
[Parameter(Position=0,Mandatory=1)]
[string]$UnpassedMandatoryParameter
)
$ErrorActionPreference = 'stop'
Get-ChildItem C:\UnknownFolder\UnknownFile
@echo off
setlocal
set Version=%~1
echo.
echo All tests should return a non-zero exit code
echo To target a specific version use: TestPowerShellExitCode "-Version X"
echo (-Version 1 and -Version 2 are known to be broken)
echo.
PowerShell %Version% -File PowerShellExitTest.ps1 1>nul 2>&1
echo TEST "-File & Exit": %errorlevel%
PowerShell %Version% -File PowerShellThrowTest.ps1 1>nul 2>&1
echo TEST "-File & Throw": %errorlevel%
PowerShell %Version% -File PowerShellStopTest.ps1 1>nul 2>&1
echo TEST "-File & Stop": %errorlevel%
PowerShell %Version% -NonInteractive -File PowerShellParamTest.ps1 1>nul 2>&1
echo TEST "-File & Param": %errorlevel%
PowerShell %Version% -Command "exit 1" 1>nul 2>&1
echo TEST "-Command & Exit": %errorlevel%
PowerShell %Version% -Command "throw 'error!'" 1>nul 2>&1
echo TEST "-Command & Throw": %errorlevel%
PowerShell %Version% -Command "$ErrorActionPreference='stop';Get-ChildItem C:\UnknownFolder\UnknownFile" 1>nul 2>&1
echo TEST "-Command & Stop": %errorlevel%
@chrisoldwood
Copy link
Author

This Gist is a set of tests to show if the version of PowerShell you're using exhibits the bug where the wrong exit code is returned for some script failures. This problem is described in a blog post of mine back in 2011 - PowerShell, Throwing Exceptions & Exit Codes. The bug was formally acknowledged by Microsoft in this KB article: Incorrect error code when you run a PowerShell script at a command prompt in Windows 7 or in Windows Server 2008 R2.

My cursory testing indicates that the issue was fixed in PowerShell v3.0, however there was a hot-fix available which may be applied to PowerShell v2.0. Given it's prevalence I decided a test script might be useful to easily check what the situation was for any given machine.

You just run the master test script TestPowerShellExitCode and it runs a serious of tests and reports the exit code from PowerShell. You should get a non-zero exit code in each case, if you don't then you need to be careful in your scripts, apply the hot-fix or upgrade the version of PowerShell.

Here is what you get for PowerShell v1.0 or (an unpatched) v2.0:

> TestPowerShellExitCode
...
TEST "-File & Exit": 1
TEST "-File & Throw": 0
TEST "-File & Stop": 0
TEST "-File & Param": 0
TEST "-Command & Exit": 1
TEST "-Command & Throw": 1
TEST "-Command & Stop": 1

Here is what you get for PowerShell v3.0, v4.0 or v5.0:

> TestPowerShellExitCode
...
TEST "-File & Exit": 1
...
TEST "-File & Throw": 1
...
TEST "-File & Stop": 1
...
TEST "-File & Param": 1
TEST "-Command & Exit": 1
...
TEST "-Command & Throw": 1
...
TEST "-Command & Stop": 1

Note: It's also interesting that there is a change in behaviour from v3.0+ where we can't redirect the error output from PowerShell using the normal 1>nul 2>&1 construct with cmd.exe.

@flcdrg
Copy link

flcdrg commented Jun 29, 2016

I've reproduced the problem with PowerShell 4, but it works fine with PowerShell 5 on Windows Server 2012 R2

@cheretbe
Copy link

Recently I've found out that -version option has some serious limitations. Some background information
is here.
Basically, it can run only two versions of Powershell: the latest installed version and version 2. Instead of
all others one always gets the latest.

The behavior is the same on all current Windows versions. The difference is only in which versions of Windows
Management Framework can be installed.

Here are test results on Windows Server 2012.

  1. By default it runs version 3:
>powershell $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
3      0      -1     -1

And we can run version 2 (provided .NET Framework v2.0.50727 is installed):

>powershell -version 2 $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1

-version 3 option, as expected, gives us version 3:

>powershell -version 3 $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
3      0      -1     -1

  1. Let's install Windows Management Framework 4.0.

By default we get version 4:

>powershell $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

-version 2 option also works as expected:

>powershell -version 2 $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1

With -version 3 option comes a surprise - we get version 4 instead:

>powershell -version 3 $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

Now with -version 4 option:

>powershell -version 4 $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

  1. And finally with Windows Management Framework 5.0 installed.

Version 5 by default:

>powershell $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      0      10586  117

-version 2 and -version 5 give us versions 2 and 5 respectively:

>powershell -version 2 $PSVersionTable.PSVersion
Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1

>powershell -version 5 $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      0      10586  117

Whereas both -version 3 and version 4 give us version 5:

>powershell -version 3 $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      0      10586  117

>powershell -version 4 $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      0      10586  117

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment