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 of0
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
becoming0
, and$false
becoming1
; thus, if the script invocation is the last statement, any nonzero exit code is effectively reported as1
; preserving the specific exit code therefore requires appending; exit $LASTEXITCODE
to the command string.
- With the
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
)