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



我在编写程序时需要一些帮助。我只需要它在默认程序中启动一个文件,并跟踪该程序的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()行。

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

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

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

  • 使用pskill工具或Python中的psutil,终止start进程;该应用程序甚至没有注意到
  • 使用您喜欢的第三方命令行工具,或者只需弹出process explorer GUI之类的东西,就可以查看谁是应用程序的父级

无论如何,如果应用程序不是start的子级,那么通过查看start的子级是找不到的。

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


那么,如何做到这一点?

正如start文档所解释的:

您可以通过文件关联运行不可执行的文件,方法是键入文件名作为命令。有关使用assocftype在命令脚本中创建这些关联的更多信息…

所以,看看assocftype。您可以运行assoc来获取文件的文件类型关联,然后使用ftype来获取该文件类型的Open命令的命令字符串,然后自己填写%0等变量,然后运行它


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

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

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

最新更新