Get Legacy Exit Codes in PowerShell

Summary: Learn how to get exit codes from legacy programs or VBScript script from inside Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, here. This week we will have one guest blogger for the entire week. Sean Kearney has written a series of blog posts about Windows PowerShell and the Legacy. I am not going to be redundant by reposting his biography each and every day.

Integrating Windows PowerShell with Legacy Environments–Part 1

The class gathers in as the Scripting Guy begins to speak…a thousand eager minds ready to be filled with knowledge.

The great one—the Scripting Guy, steps up to the podium and begins with a quiet easy drawl, “So today, class, we’re going to dig deeper into the mysteries of Windows PowerShell, write ourselves some cool advanced functions, play a little with regular expressions, perhaps write a module…”

A small, shrill voice pipes up, “Oh! Oh! Oh! Oh!”

The Master pauses and looks over. A disheveled and somewhat fidgety little man at the back of the room is wildly jumping up and down with his arms waving…

“Oh! Oh! Oh!” the little creature continues.

The Scripting Guy, always eager to encourage interest, politely nods to encourage the young one to finish his question.

“Scripting Guy!” he pipes up eagerly. “I love Windows PowerShell, but I read on the Hey! Scripting Guy blog that Windows Powershell will play nice with VBScript! Could you tell us more about this? Nobody documents it online. There’s no FAQs, it’s…it’s unbelieved! Please tell us more!”

The Scripting Guy paused, “And who are you, so eager to learn the mysteries of the Legacy and Windows PowerShell?”

“They call me Sean. Please tell me more, O Master of Scripting.”

The Scripting Guy nods. “And so we shall…” he stated as he invoked the following cmdlet.

GET-CONTENT C:PowershellLegacy1.txt | more

One of the misconceptions that people have about working with script, console applications, and Windows PowerShell is that there is no way to pass parameters and receive exit codes. I once believed this to be true as well. But Windows PowerShell is truly a “powerful” shell because it does not destroy what we already have.

Within console applications and VBScript scripts, normally we would receive the error that was last reported by the following variable:

%ERRORLEVEL%

Or VBScript would pass back a variable such as ThisVariable after we invoke an application like the following.

DIM OBJSHELL=Wscript.NewObject(“Wscript.Shell”)

APP=“CMD.EXE /C PROGRAM.CMD“

THISVARIABLE=OBJSHELL.RUN(APP)

Now if we tried this in Windows PowerShell, we would be stymied because $ErrorLevel doesn’t exist, accessing $ENV:ERRORLEVEL doesn’t work worth a darn, and calling a console application like the following only returns the results from the screen as an object.

$THISVARIABLE=(& ‘PROGRAM.CMD’)

So you stare at the Windows PowerShell console helplessly, frustrated, and crying for a solution to beings who won’t listen…not knowing that the answer is in front of you the whole time.

Within Windows PowerShell, there is a variable called $LastExitCode.

Yes, it’s…

(Wait for it…wait for it…pause for effect…) the Windows PowerShell equivalent of %ERRORLEVEL%. The wonderful part is that it works exactly the same. If you invoke a console application or a VBScript script that would return something to %ERRORLEVEL%, from within Windows PowerShell, you’ll get the response in $LastExitCode.

Now it gets better. If you call Windows PowerShell scripts from a console application or a VBScript script as follows, they also return a value.

POWERSHELL.EXE –FILE Scriptname.PS1 –executionpolicy RemoteSigned

By default, if it doesn’t throw an error, it will return 0; or it will return 1 if something bad happens.

Now also take note, folks. If within a Windows PowerShell script, you execute a line such as the following, that value will also be returned to the console application or a VBScript script as normal.

EXIT 42

or

RETURN 24

The Scripting Guy looks at the back of the room as the text file ends on the screen.

The little fuzzy haired one is chomping away eagerly on a box of popcorn. The floor is littered with kernels. “More! More, more, MORE!” he bursts with popcorn flying in the air.

“Young one, that is for another blog post. For now you must learn patience. Tomorrow we will discuss passing variables to Windows PowerShell from a console application or a VBScript script.”

The little one unhappily slumps back in his chair, chewing on a Rubik’s Cube.

Guest blogger week will continue tomorrow when Sean will continue to talk about Windows PowerShell and the Legacy. A special thank you to Sean for writing this week’s blog posts. Hope you enjoy them.

It looks like if one invokes a powershell ps1 script from windows cmd shell via `powershell -file .pathtofile.ps1` and that file exits with a non-zero code to indicate an error, the powershell process doesn't pass that on up to the calling shell.