0

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

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()线。

如果有人知道如何实现我的要求,我们将不胜感激!谢谢

4

1 回答 1

3

好吧,首先,试着把它分解成碎片,而不是试图猜测那个大表情中哪里出了问题。打印出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 机制,在这种情况下,这是一个糟糕的例子……</sub>

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

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

无论如何,如果应用程序不是 的子级start,您无法通过查看 的子级来找到它start

此外,如果您查看后面的 Win32 API start(和 Python 的os.startfile, ShellExecute,请注意在现代 Windows 中,它甚至不返回进程的句柄。


那么,你怎么做到这一点呢?

好吧,正如start文档解释的那样:

您可以通过将文件名作为命令键入来通过文件关联运行不可执行文件。assoc有关使用和在命令脚本中创建这些关联的更多信息ftype……</p>

所以,看assocftype。您可以运行assoc来获取文件的文件类型关联,然后使用ftype来获取该文件类型的命令的命令字符串Open,然后自己填写%0等变量,然后运行它。(如果命令不是命令字符串,那么它是一个旧的 OLE 类型的程序,你不能这样做——但这正是你可能一开始就没有得到新进程的情况……)


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

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

如果你这样做,你可以SEE_MASK_NOCLOSEPROCESSfMask标志中设置,并且该hProcess成员将是HINSTANCE进程的一个成员(但只有在启动新进程时——如果 shell 扩展找到现有进程或其他什么,你仍然会在这里得到 NULL , 当然)。然后,您可以在其上使用普通的 Win32 进程 API,或者仅获取其 pid 并将其与psutil. 这一切都是可行的,但可能很痛苦,使用ctypes; 你可能想使用pywin32包装器。

于 2015-04-20T05:14:47.163 回答