I'm trying to create a python script that starts a new window and waits for it to complete, and then retrieve the exit code. So I am using Popen with start /wait
to create a separate window for it, but this does not properly forward the exit code.
This code summarizes the problem:
import subprocess
params = {}
params['stdout'] = subprocess.PIPE
params['stderr'] = subprocess.PIPE
params['shell'] = True
proc = subprocess.Popen('start /wait cmd /c exit 1', **params)
# This works but the above line does not
#proc = subprocess.Popen('exit 1', **params)
resultCode = proc.wait()
print(resultCode)
The documentation for start /wait
suggests that it should return the exit code, and when I run it manually and then check %ERRORLEVEL%
it appears correct, so I'm not sure what I'm doing wrong
CMD's start
command always succeeds overall if it successfully executes the given command via CreateProcess
or ShellExecuteEx
. It succeeds even if it's instructed to /wait
and ends up setting %errorlevel%
to a non-zero value. You can see this by running (start /wait exit 1) && echo success
. The &&
operator only executes the right-hand expression if the left-hand expression succeeds.
To work around this, you can manually exit the initial shell using the !errorlevel!
value that gets set by start
. For example:
command = 'exit 1'
shell_path = os.environ.get('ComSpec', 'cmd.exe')
start_command = 'start "" /wait {}'.format(command)
cmdline = '"{shell}" /v:on /c "({command}) & exit !errorlevel!"'.format(
shell=shell_path, command=start_command)
proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Note that the above Popen
call does not use the shell=True
argument because the shell needs to be run manually with the /v:on
option. This enables delayed expansion of environment variables, using "!" instead of "%".
That said, you don't need the shell for your stated objective. Simply have the child process create a new console by passing the CREATE_NEW_CONSOLE
creation flag as follows:
proc = subprocess.Popen(args, creationflags=subprocess.CREATE_NEW_CONSOLE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)