Hi cyberpals. Today I was messing around with some Windows utilities and realized that I didn’t fully understand how to handle exit values.
On *nix systems, you can do something like this:
daniel@disstrack ~ % cat exit.c
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc > 1)
return atoi(argv[1]);
return 0;
}
daniel@disstrack ~ % gcc -o exit exit.c
daniel@disstrack ~ % ./exit
daniel@disstrack ~ % echo $?
0
The exit value can be up to 255. It rolls over:
daniel@disstrack ~ % ./exit 256 daniel@disstrack ~ % echo $? 0 daniel@disstrack ~ % ./exit 7000 daniel@disstrack ~ % echo $? 88 # Why is this 88??? daniel@disstrack ~ % python3 Python 3.5.2 (default, Nov 12 2018, 13:43:14) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> 7000 % 256 88 # That's why.
Checking exit values can be useful if a utility’s author made them meaningful. Some programs such as curl have several dozen exit codes. See it’s man page for more details. Other utilities such as cp return a 0 if it was successful, or a 1 if it was not. This comes in handy when you’re writing shell scripts.
It turns out, Windows programs also have exit values. Powershell supports the $? method outlined above, but will show True or False rather than the value. To see the actual value, use $lastexitcode:
PS C:\Users\dmfr\lolwindows> type exit.c
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc > 1)
return atoi(argv[1]);
return 0;
}
PS C:\Users\dmfr\lolwindows> C:\MinGW\bin\gcc -o exit.exe exit.c
PS C:\Users\dmfr\lolwindows> ./exit.exe
PS C:\Users\dmfr\lolwindows> $?
True
PS C:\Users\dmfr\lolwindows> .\exit.exe 1
PS C:\Users\dmfr\lolwindows> $?
False
PS C:\Users\dmfr\lolwindows> $lastexitcode
1
PS C:\Users\dmfr\lolwindows> .\exit.exe 7000
PS C:\Users\dmfr\lolwindows> $lastexitcode
7000
Neat. It looks like Windows supports values greater than 255 for exit value. After a bit of Googling, I found that these are stored as 32 bit signed integers, and that there are thousands of different error conditions defined in WinError.h: https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes–0-499-
Here’s an example showing that this is in fact a 32 bit integer:
PS C:\Users\dmfr\lolwindows> .\exit.exe 2147483647 PS C:\Users\dmfr\lolwindows> $lastexitcode 2147483647 PS C:\Users\dmfr\lolwindows> .\exit.exe 2147483648 PS C:\Users\dmfr\lolwindows> $lastexitcode -2147483648
cmd is a different beast. It does not support $?. Use %ERRORLEVEL% instead:
C:\Users\dmfr\lolwindows>exit.exe C:\Users\dmfr\lolwindows>echo %errorlevel% 0 C:\Users\dmfr\lolwindows>exit.exe 7000 C:\Users\dmfr\lolwindows>echo %errorlevel% 7000
I hope you enjoyed this nerdy blog post.