Eryk Sun added the comment: > An .lnk is launched with ShellExecute which returns control > immediately upon successful launch
cmd calls ShellExecuteEx, not ShellExecute, and it uses the flags SEE_MASK_NO_CONSOLE (0x8000, don't create a new console) and SEE_MASK_NOCLOSEPROCESS (0x0040, return a process handle if possible). Here's a walk-through with a debugger attached to cmd while executing a LNK shortcut to "C:\Program Files\Python27\python.exe": C:\Temp>.\python.lnk -c "import sys,time;time.sleep(60);sys.exit(42)" Breakpoint 0 hit SHELL32!ShellExecuteExW: 00007ff9`a5710e20 48895c2408 mov qword ptr [rsp+8],rbx ss:000000a3`eb3af3a0=000000a3eb597ca0 0:000> ; as /x info @rcx 0:000> ; as /x sz @@(*((unsigned long *)${info})) 0:000> bd 2,3,4; pt; be 2,3,4 ShellExecuteEx returns the process handle: 0:000> ?? *((void **)(${info} + ${sz} - 8)); * hProcess void * 0x00000000`000002fc 0:000> !handle 2fc Handle 2fc Type Process 0:000> g cmd uses the handle to read the ImageSubsystem type from the process environment block (PEB), for which 3 is a console process and 2 is a GUI process. Breakpoint 1 hit cmd!GetProcessSubsystemType: 00007ff7`a133faf4 48895c2410 mov qword ptr [rsp+10h],rbx ss:000000a3`eb3af458=000000a3eb585640 0:000> g Breakpoint 2 hit KERNELBASE!ReadProcessMemory: 00007ff9`a49ac230 4883ec48 sub rsp,48h 0:000> as /x buf @r8 0:000> pt KERNELBASE!ReadProcessMemory+0x2b: 00007ff9`a49ac25b c3 ret 0:000> ?? ((ntdll!_PEB *)${buf})->ImageSubsystem unsigned long 3 0:000> g Since it's a console process, cmd waits and queries the exit code. Breakpoint 3 hit KERNELBASE!WaitForSingleObject: 00007ff9`a49840c0 4533c0 xor r8d,r8d 0:000> r rcx rcx=00000000000002fc 0:000> g Breakpoint 4 hit KERNELBASE!GetExitCodeProcess: 00007ff9`a49c46d0 4053 push rbx 0:000> as /x rc @rdx 0:000> pt KERNELBASE!GetExitCodeProcess+0x3a: 00007ff9`a49c470a c3 ret 0:000> ?? *((unsigned long *)${rc}) unsigned long 0x2a 0:000> ? 0x2a Evaluate expression: 42 = 00000000`0000002a It sets the exit code in the 'hidden' environment variable "=ExitCode" as a unsigned hexadecimal number. C:\Temp>echo %=ExitCode% 0000002A You can also query the signed value using the pseudo environment variable "errorlevel". C:\Temp>echo %errorlevel% 42 ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue26189> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com