2

I am using subprocess.Popen in order to run some executable from the CMD shell:

p = subprocess.Popen('cmd /c start app.exe')

I am having problems closing the console window when killing CMD via p.terminate(). If I do it right away, then the console window doesn't even open. If I do it after some time, then the console window doesn't close.

The app.exe that CMD runs is a server, listening to some other process. When that other process is done, I need to close the server along with the console window to which it is attached.

I believe that p is in fact a handle to the start app.exe batch script, and not to the actual CMD shell.

Here is my full script:

import subprocess
p1 = subprocess.Popen('cmd /c start app.exe')
p2 = subprocess.Popen('cmd /c call test.exe')
p2.wait()
p1.terminate()

I have also tried this (based on this answer):

import subprocess, psutil
p1 = subprocess.Popen('cmd /c start app.exe')
p2 = subprocess.Popen('cmd /c call test.exe')
p2.wait()
pobj = psutil.Process(p1.pid)
pobj.terminate()

But got a NoSuchProcess exception.

From some of the answers that I've found on similar questions, I think it can be done by the title of the window, but I would really like to avoid this clumsy workaround.

halfer
  • 19,824
  • 17
  • 99
  • 186
goodvibration
  • 5,980
  • 4
  • 28
  • 61
  • check https://stackoverflow.com/questions/7989922/opening-a-process-with-popen-and-getting-the-pid – Sharad Feb 05 '18 at 15:26
  • @Sharad: Tried both `shell=False` and `shell=True`. No change. – goodvibration Feb 05 '18 at 15:28
  • Do you actually need the `start` part? – glglgl Feb 05 '18 at 15:29
  • @glglgl: Yes, otherwise it is opened in the same terminal in which I am running, and all the printouts are messed up in it (both server's and client's). – goodvibration Feb 05 '18 at 15:33
  • 2
    You do not want to use CMD here at all. You're only using it to get a new console. Instead, run "app.exe" directly with the parameter `creationflags=subprocess.CREATE_NEW_CONSOLE`. Then `p` will refer to the "app.exe" process. If "app.exe" is the only process that's attached to the console that it allocates (i.e. no lingering child processes), then the console will automatically close after `p.terminate()` kills "app.exe". – Eryk Sun Feb 05 '18 at 23:43
  • @eryksun: Thank you. However, `p1.terminate()` does not seem to close the console in which "app.exe" is running. – goodvibration Feb 06 '18 at 10:18
  • Did you run it as `p1 = subprocess.Popen('app.exe', creationflags=subprocess.CREATE_NEW_CONSOLE)`? – Eryk Sun Feb 06 '18 at 10:26
  • @eryksun: Yes. The only way that I can successfully terminate it is if I run it in the same console as my python script (i.e., without `CREATE_NEW_CONSOLE`). I wouldn't mind it so much, but the problem is that I need to create the other process, run it to completion and then terminate this process. Now, if I create the other process in the same console, then I get all the printouts (of both processes) messed up. And if I create the other process in another window, then I cannot wait for its completion (its console remains opened, therefore it never "really completes"). – goodvibration Feb 06 '18 at 10:42
  • @eryksun: In short, I need to direct their printouts to two different consoles, and I need to be able to terminate the server after the client completes. – goodvibration Feb 06 '18 at 10:43
  • You're not having a problem terminating app.exe. That *must* work. You have an all-access handle. So app.exe has to be creating child processes that are attached to its console that remain running after app.exe has been terminated. Juggling consoles to attach to and close its console is possible, but I'd probably go straight to the general solution of a Job object. – Eryk Sun Feb 06 '18 at 11:01

0 Answers0