2

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

2
  • @OferSadan I've updated the code to remove unnecessary imports and problem persists Commented May 13, 2018 at 10:52
  • I have tried to replicate it with both types of imports and I get the same results as you, so apologies for the mistake Commented May 13, 2018 at 10:53

2 Answers 2

3

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)
Sign up to request clarification or add additional context in comments.

Comments

0

Using

proc = subprocess.Popen('call cmd /c exit 1', **params)

Instead of your start /wait returns the error code 1 in resultCode.

By the logic of this question and answer: CALL command vs. START with /WAIT option

My guess would be that the difference is that start /wait doesn't share variables with the same environment and call does.

1 Comment

Thanks, but I'm looking for a solution that opens up a separate command line window which does not happen when using CALL

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.