在python中打开一个文件并跟踪其默认应用程序的pid

时间:2015-04-20 05:05:53

标签: python subprocess pid psutil

我需要帮助我写一个程序。我需要做的就是在默认程序中启动一个文件并跟踪该程序的PID(以便稍后关闭)。我从here找到了以下代码:

import psutil
import subprocess
import os

file = os.getcwd() + "\\" + input()
open = subprocess.Popen(["start", "/WAIT", file], shell=True)
psutil.Process(open.pid).get_children()[0].kill()

这会在正确的程序中打开文件,但它会以

崩溃
IndexError: list index out of range  error on the 

psutil.Process(open.pid).get_children()[0].kill()行。

如果有人知道如何实现我的要求,我们将非常感谢您的帮助!感谢

1 个答案:

答案 0 :(得分:2)

嗯,首先,尝试将其分解成碎片,而不是试图猜测那个大表达中哪里出了问题。打印出open.pidProcess(open.pid)Process(open.pid).get_children()Process(open.pid).get_children()[0],问题非常明显:start进程没有子进程。

其次,start并不总是启动新进程。它为一个进程运行Open命令 - 它可以是一个命令字符串,或者它可以是一个OLE东西或通过shell扩展DLL调用的东西,可能最终启动一个新的进程,但它可以做其他事情,最常见的是在该应用程序的现有进程中打开文件。例如,如果你给它一个.docx文件,并且Word已经打开,它会要求现有的Word副本处理该文件。 *

*虽然在现代版本的Word中,我认为它实际上是word.exe,而不是依赖于旧的OLE机制,在这种情况下,这是一个不好的例子...... < / p>

即使它必须开始一个新的过程,它也不一定像受控制的孩子那样;它可能会启动一个新的分离进程,然后就像它通过OLE找到一个一样。我很确定细节没有记录,但它是有道理的(想象一下,如果你是这样的话你怎么写start),你可以很容易地测试它:

  • 使用Python中的pskill工具或psutil来杀死start进程;该应用程序甚至没有注意到。
  • 使用您最喜欢的第三方命令行工具,或者只是弹出流程资源管理器GUI,看看该应用程序的父级是谁。

无论如何,如果应用不是start的孩子,则无法通过查看start的孩子找到它。

另外,如果你看一下start(以及Python的os.startfileShellExecute后面的Win32 API,请注意在现代Windows中它甚至没有返回进程的句柄


那么如何你这样做?

好吧,正如start文档解释:

  

通过键入文件名作为命令,可以通过文件关联运行不可执行文件。有关使用assocftype ...

在命令脚本中创建这些关联的详细信息

所以,请查看assocftype。您可以运行assoc来获取文件的文件类型关联,然后使用ftype获取该文件类型的Open命令的命令字符串,然后填写{{1变量自己,然后运行它。 (如果命令不是命令字符串,那么它是一个旧的OLE类型程序,你不能这样做 - 但那就是你可能没有首先获得新进程的情况......)< / p>


或者,您可能已经注意到%0文档说:

  

要获取有关因调用ShellExecute而启动的应用程序的相关信息,请使用ShellExecuteEx

如果您这样做,则可以在ShellExecute标记中设置SEE_MASK_NOCLOSEPROCESS,并且fMask成员将为hProcess进程(但仅限于{1}}启动了新进程 - 如果shell扩展发现了现有进程或其他什么,当然你仍然会在这里得到NULL。然后,您可以在其上使用常规的Win32流程API,或者只是获取其pid并将其与HINSTANCE一起使用。这是可行的,但可能很痛苦,psutil;你可能想要使用ctypes包装器。