-command's exit code is not the same as a scri

2019-01-15 05:41发布

问题:

I need to run a script with PowerShell -Command "& scriptname", and I would really like it if the exit code I got back from PowerShell was the same as the exit code the script itself returned. Unfortunately, PowerShell returns 0 if the script returns 0, and 1 if the script returns any non-zero value as illustrated below:

PS C:\test> cat foo.ps1
exit 42
PS C:\test> ./foo.ps1
PS C:\test> echo $lastexitcode
42
PS C:\test> powershell -Command "exit 42"
PS C:\test> echo $lastexitcode
42
PS C:\test> powershell -Command "& ./foo.ps1"
PS C:\test> echo $lastexitcode
1
PS C:\test>

Using [Environment]::Exit(42) almost works:

PS C:\test> cat .\baz.ps1
[Environment]::Exit(42)
PS C:\test> powershell -Command "& ./baz.ps1"
PS C:\test> echo $lastexitcode
42
PS C:\test>

Except that when the script is run interactively, it exits the whole shell. Any suggestions?

回答1:

If you look at the part you are sending to -Command as a script you will see it would never work. The script running the 'foo.ps1' script does not have a call to exit, so it does not return an exit code.

If you do return an exit code it will do what you want. Also change it from " to ', otherwise $lastexitcode will be resolved before you 'send' the string to the second PowerShell if you run it from PowerShell.

PS C:\test> powershell -Command './foo.ps1; exit $LASTEXITCODE'
PS C:\test> echo $lastexitcode
42

PS: Also check out the -File parameter if you just want to run a script. But also know it does not return 1 if you have a terminating error as -Command does. See here for more on that last topic.

PS C:\test> powershell -File './foo.ps1'
PS C:\test> echo $lastexitcode
42


回答2:

CAVEAT: If your PowerShell script returns exitcodes HIGHER THAN 65535, they roll over:

$exitCode = 65536
Exit $exitCode

If the following CMD calls this PS1 script above, your will get an %errorlevel% of 0

Powershell.exe "& 'MyPowershellScript.ps1' "; exit $LASTEXITCODE
SET ERR=%ERRORLEVEL%

and an exitcode of 65537 would give you an %errorlevel% of 1, etc.

Meanwhile, if a CMD calls another and the child script returns an errorlevel higher than 65535, it passes through just fine.

Cmd /c exit 86666

The CMD Will return an %errorlevel% of 86666 as expected.

CAVEAT to all of this: Now this is happening on and off for no apparent reason.



回答3:

How are you calling your script interactively?

I have tried this and it seems to work OK, but I call it from DOS prompt, not within PowerShell

C:\Temp>type foo.ps1
exit 42


C:\Temp>powershell -noprofile -nologo -noninteractive -executionpolicy Bypass -file .\foo.ps1

C:\Temp>echo %errorlevel%
42

c:\Temp>