我需要帮助我写一个程序。我需要做的就是在默认程序中启动一个文件并跟踪该程序的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()
行。
如果有人知道如何实现我的要求,我们将非常感谢您的帮助!感谢
答案 0 :(得分:2)
嗯,首先,尝试将其分解成碎片,而不是试图猜测那个大表达中哪里出了问题。打印出open.pid
,Process(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
),你可以很容易地测试它:
pskill
工具或psutil
来杀死start
进程;该应用程序甚至没有注意到。无论如何,如果应用不是start
的孩子,则无法通过查看start
的孩子找到它。
另外,如果你看一下start
(以及Python的os.startfile
,ShellExecute
后面的Win32 API,请注意在现代Windows中它甚至没有返回进程的句柄
那么如何你这样做?
好吧,正如start
文档解释:
通过键入文件名作为命令,可以通过文件关联运行不可执行文件。有关使用
在命令脚本中创建这些关联的详细信息assoc
和ftype
...
所以,请查看assoc
和ftype
。您可以运行assoc
来获取文件的文件类型关联,然后使用ftype
获取该文件类型的Open
命令的命令字符串,然后填写{{1变量自己,然后运行它。 (如果命令不是命令字符串,那么它是一个旧的OLE类型程序,你不能这样做 - 但那就是你可能没有首先获得新进程的情况......)< / p>
或者,您可能已经注意到%0
文档说:
要获取有关因调用
ShellExecute
而启动的应用程序的相关信息,请使用ShellExecuteEx
。
如果您这样做,则可以在ShellExecute
标记中设置SEE_MASK_NOCLOSEPROCESS
,并且fMask
成员将为hProcess
进程(但仅限于{1}}启动了新进程 - 如果shell扩展发现了现有进程或其他什么,当然你仍然会在这里得到NULL。然后,您可以在其上使用常规的Win32流程API,或者只是获取其pid并将其与HINSTANCE
一起使用。这是可行的,但可能很痛苦,psutil
;你可能想要使用ctypes
包装器。