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.