2

I'm trying to kill an .exe with subprocess.Popen.

Solution as:

  1. taskkill /im (.exe) /t /f
  2. taskkill /pid (.exe) /t /f

aren't working as the response is access denied. Indeed, as i'm running the cmd from subprocess i'm not able to obtain admin privilegies.

I've found a command to kill this process from cmd (without running it as admin) which is:

  1. wmic process where name=".exe" delete

... but when i'm running it with subprocess it gives me "invalid query". The command i'm running is:

4)subprocess.Popen(['wmic', 'process', 'where', 'name="-------.exe"', 'delete'], shell=True, stdout=subprocess.PIPE)

I suppose that i'm writing it wrongly. Some advices?

matebende
  • 543
  • 1
  • 7
  • 21
BloomShell
  • 833
  • 1
  • 5
  • 20
  • 1
    Try removing the quotes around the filename, since you are specifying separate arguments here anyway. Does that work? – CherryDT Jul 26 '20 at 09:50
  • 5) subprocess.Popen(['wmic', 'process', 'where', 'name=openvpn.exe', 'delete'], shell=True) ... always invalid query :( – BloomShell Jul 26 '20 at 09:52
  • 2
    Sounds like some weird escaping incompatibility... A shot in the dark and probably not the best solution: `['cmd', '/c', 'wmic process where name="openvpn.exe" delete']` or maybe just pass the whole thing as string: `subprocess.popen('wmic process where name="openvpn.exe" delete')` – CherryDT Jul 26 '20 at 09:54
  • I've just found the solution in a reddit answer :). Thank you Cherry for you time :) – BloomShell Jul 26 '20 at 09:57
  • 1
    Next thing I would do is use [Process Monitor](https://learn.microsoft.com/en-us/sysinternals/downloads/procmon) to see what command line is _actually_ passed to wmic (set filter to "operation" "begins with" "process") and compare it to how it looks when you do it from cmd where it works. That may give a clue about what's wrong. – CherryDT Jul 26 '20 at 09:59
  • 1
    Oh, cool. In that case, it would be nice if you would write an answer to your own question, so that future readers can find the solution too! You can later also self-accept the answer. – CherryDT Jul 26 '20 at 09:59
  • 1
    You should not mix a list of arguments with `shell=True`; it sometimes happens to work in weird ways, but is basically always an error. See also https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess – tripleee Jul 26 '20 at 10:10

1 Answers1

2

The solution is to put spaces around the comparison operator and send the whole condition (name = xxx or name like xxx) as single argument, since wmic doesn't like it to be split in parts, and internally the quotes get messed up if they are in the "middle" of a word:

subprocess.Popen(['wmic', 'process', 'where', 'name like "----.exe"', 'delete'], shell=True)
CherryDT
  • 25,571
  • 5
  • 49
  • 74
BloomShell
  • 833
  • 1
  • 5
  • 20
  • Actually both shell=False and shell=True works. I'm a newbie and do not know the complications that could arise from shell=True. Any explanation? For example, when I lauch the .exe with the proper commands with subprocess it needs shell=True otherwise an error occurs. Instead, when using wmic if shell =False the error does not appear. – BloomShell Jul 26 '20 at 10:24
  • My other comment has a link to more information. Basically, this currently happens to work on Windows, but that doesn't mean it's correct; once you read the linked page, it should be obvious why not. – tripleee Jul 26 '20 at 10:26
  • It's "wmic.exe", not a `wmic` shell command, and you're not using any shell command-line features such as environment-variable expansion or standard I/O redirection and piping, so using `shell=True` here is pointless. – Eryk Sun Jul 26 '20 at 15:58
  • This command is Windows only, so there's also no point in worrying about whether wmic.exe is compatible with the assumptions in `subprocess.list2cmdline`. In fact, wmic.exe calls `GetCommandLineW` and manually parses its command line instead of using C `argv` or `CommandLineToArgvW`, so it is not a normal case that's predictably compatible with passing the arguments as a list. Just use a command line string, e.g. `subprocess.call('wmic.exe process where "name like "----.exe"" delete')`. – Eryk Sun Jul 26 '20 at 15:59
  • More simply, terminate a process by PID via `os.kill(pid, signal.SIGTERM)`. In Windows this is implemented via `TerminateProcess(hProcess, SIGTERM)`, which sets the exit status to `SIGTERM` (15). That's not a meaningful exit status in Windows, but fine. Normally in Windows the exit status of a terminated process is set to 1, but `os.kill` is written appallingly bad and conflates this with trying to send `CTRL_BREAK_EVENT` (1) to a console group, with the given ID ineterpreted as a console process group ID. Only do this if it's actually a console process group that you're sending Ctrl+Break. – Eryk Sun Jul 26 '20 at 16:10