Home > Net >  Powershell: Difference between exit and exit with a value
Powershell: Difference between exit and exit with a value

Time:09-03

I noticed a strange behaviour in Powershell. There are two .ps1 files:

main.ps1:

echo "running exit.ps1"
$myexitcode = & ".\exit.ps1" "hello" | select -Last 1 
echo "Return code is $myexitcode"
echo "Exit code is $?"
echo "after running exit.ps1"

exit.ps1:

echo "processing args " $args
$script:_serverExitStatus = 9

#this is causing the program to exit completely
[System.Environment]::exit(3)

#BUT this is NOT causing the program to exit completely
#[System.Environment]::exit

With the above code, the process is getting completely exited and the output doesn't contain "after running exit.ps1". However, if I comment [System.Environment]::exit(3) and uncomment [System.Environment]::exit, output contains "after running exit.ps1"

I feel that exit must always exit completely. But, that's not the case with [System.Environment]::exit

What is the difference between these two things and which one is correct?

Version:

$PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      22000  832

Thank you.

CodePudding user response:

To elaborate on Abdul Niyas P M's helpful answer:

In PowerShell, referencing a .NET method without () doesn't actually invoke the method, it prints its signatures (overload definitions), i.e. it performs reflection to show you what arguments you'd have to pass in an actual invocation:

PS> [System.Environment]::Exit

OverloadDefinitions
-------------------
static void Exit(int exitCode)

As you can see, the method takes an unconditional int-typed argument specifying the exit code to report, which implies that you must pass a value on invocation; if you want to signal success, simply use [System.Environment]::Exit(0)

However, I wonder if this method is really the right tool for your task, and whether use of PowerShell's exit statement is what you're looking for - see below.


  • Use PowerShell's exit statement to exit the running script.

    • Without an argument, 0 is reported as the exit code; pass a number to set the exit code explicitly (e.g. exit 3).

    • Inside a PowerShell session, this exit code is reported in the automatic $LASTEXITCODE variable, not in the automatic $? variable - the latter is an abstract success indicator in the form of a Boolean value ($true or $false), and it effectively translates a $LASTEXITCODE value of 0 to $true, and any nonzero value to $false.

    • When a script is invoked via PowerShell's CLI (powershell.exe for Windows PowerShell, pwsh for PowerShell (Core) 7 ):

      • With the -File parameter, the exit code also becomes the PowerShell process' exit code
      • With the (potentially implied) -Command parameter, it is the value of $? after the last statement executes that is translated to an exit code, with $true becoming 0, and $false becoming 1; thus, if the script invocation is the last statement, any nonzero exit code is effectively reported as 1; preserving the specific exit code therefore requires appending ; exit $LASTEXITCODE to the command string.
  • Use the [System.Environment]::exit($number) .NET method to instantly exit (terminate) the current process and thereby the whole PowerShell session.

    • Therefore, it's best to avoid this method, unless you truly need to unconditionally terminate the entire process.

CodePudding user response:

[System.Environment]::exit is a static method and requires () and exitCode parameter to do the actual work. So [System.Environment]::exit(3) is the actual code that terminates the process with status code(3)

  • Related