Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning an exit code from a PowerShell script

Tags:

powershell

I have questions about returning an exit code value from PowerShell when run from a cmd.exe invocation. I found https://weblogs.asp.net/soever/returning-an-exit-code-from-a-powershell-script which has been helpful. But, the solution for PowerShell code is to add a function.

function ExitWithCode { param($exitcode) $host.SetShouldExit($exitcode) exit }

Generates:

ExitWithCode : The term 'ExitWithCode' 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:\src\t\e\exit5.ps1:6 char:1
+ ExitWithCode -exitcode 12345
+ ~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (ExitWithCode:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

But, placing the "exit" on a new line works. Is this just a language anomaly?

function ExitWithCode { param($exitcode) $host.SetShouldExit($exitcode)
exit }

Also, this page is from 2010. Is this still the current state? Is there a better/easier way now?

like image 702
lit Avatar asked May 06 '18 13:05

lit


People also ask

How do I return a value from a PowerShell script?

In general, the return keyword exits a function, script, or script block. So, for example, we can use it to leave a scope at a specific point, return a value, or indicate that the scope's end has been reached.

Does return exit the function PowerShell?

The return keyword exits a function, script, or script block. It can be used to exit a scope at a specific point, to return a value, or to indicate that the end of the scope has been reached.

How do I echo in PowerShell?

Type “Write-Output” in the scripting pane of the “PowerShell ISE“, and then write hyphen (-). A dropdown menu will be activated, which contains the supported parameter: For instance, the echo/Write-Output command prints the output as an individual expression.


1 Answers

Guenther Schmitz's answer solves your immediate syntax problem, but it's important to note that $host.SetShouldExit() is not meant to be called by user code, as implied by Bruce Payette's answer.

Instead, it is used internally by PowerShell itself in response to an exit statement in user code.

The only conceivable reason to use it is to repurpose it for implementing a workaround around a limitation of exit-code reporting when a script is being called via the -Command
(-c) parameter of PowerShell's CLI
:

With -Command, a script's specific non-zero exit code is always translated to 1, so the specific exit code is lost - see this answer for an overview of exit-code handling in PowerShell.

$host.SetShouldExit(), despite not being intended for this purpose, happens to overcome this limitation and ensures that the script's exit code is also reported as the PowerShell process' exit code.

This workaround must not be applied when the script is being called from an interactive PowerShell session, because it will cause the session as a whole to exit instantly, which is the subject of your follow-up question.

Reliable detection of when a script is being called via -Command is nontrivial and hard to make fully reliable, however, as shown in this answer to your follow-up question.

The better approach is not to use the $host.SetShouldExit() workaround and do the following instead.

  • Invoke your script via the -File CLI parameter, in which case no workaround is needed: Just use exit $n in your script, and $n will be reported as the PowerShell process' exit code (assuming $n is an integer).

  • When calling via -Command, follow the script call with ; exit $LASTEXITCODE in the command string so as to ensure that the script's exit code is passed through.

Of course, you may not always be in control of how your script is invoked via the CLI; in that event, the workaround is worth considering.

like image 177
mklement0 Avatar answered Oct 26 '22 18:10

mklement0