使用Python优雅地杀死Chrome for Windows

问题描述 投票:0回答:1

我一直试图确定一种方法来关闭Chrome(和其他进程),优雅地利用Python。我已经通过了一些方法,但所有这些都导致Chrome显示一条消息,指出“Chrome未正确关闭”。使用“还原”按钮。从Windows中的任务管理器关闭程序时不会发生这种情况。我编写了一个程序,利用Falcon提供API访问来关闭“托管”程序。代码与此无关,但以下是我尝试过的方法,可以关闭运行良好但不优雅的Chrome。

def stop_app(app_exe):
    for process in psutil.process_iter():
        if process.name() == app_exe:
            process.terminate()

备用:

for process in psutil.process_iter():
    if process.name() == app_exe:
        children = process.children(recursive=True)
        children.append(process)
        for p in children:
            p.send_signal(signal.CTRL_BREAK_EVENT)

我也试过kill()代替terminate(),各种信号类型(Windows实际上只支持三种,CTRL_BREAK_EVENT,CTRL_C_EVENT,SIGTERM)。

我也尝试过使用win32库,我遇到了同样的问题。 Win32也不是平台无关的,我发现win32 / wmi库在寻找运行的Windows进程时会占用大量的系统资源。 psutil库允许与平台无关,并且在迭代Windows进程时没有相同的性能问题。这是代码。

c = wmi.WMI()
for process in c.Win32_Process():
    if process.Name == app_exe:
        process.Terminate()

那里的任何人尝试类似的东西,并想出一个解决方案?

每个CristiFati建议的快速解决方案:

def enumWindowsProc(hwnd, lParam):
    if (lParam is None) or ((lParam is not None) and 
          win32process.GetWindowThreadProcessId(hwnd)[1] == pid)):
        text = win32gui.GetWindowText(hwnd)
        if text:
            wStyle = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE)
            if wStyle & win32con.WS_VISIBLE:
                win32api.SendMessage(hwnd, win32con.WM_CLOSE)


def stop_app(app_exe):
    for process in psutil.process_iter():
        if process.name() == app_exe:
            win32gui.EnumWindows(enumWindowsProc, process.pid)
python browser wmi pywin32 psutil
1个回答
2
投票

显然,Chrome因流程终止而关闭时不满意。它有一种检测这种确切情况的机制。 它运行了一堆进程,我认为这可能是一种优雅地关闭它的方式(我可能错了,但我记得一旦我设法做到了),通过仔细选择进程被杀死的顺序(crashpad) - 处理程序,实用程序,渲染器,在主人之前),但现在我不能这样做,我也不知道实际上有多优雅。

注意:我个人认为这种行为非常有用,因为我有许多打开的Chrome窗口,每个窗口都有很多标签,每次我需要重新启动笔记本电脑时,我都会从任务管理器关闭Chrome,以便下次打开它时它会恢复当前状态。

回到我们的问题,一种方法是获取它的窗口并发送它[MS.Docs]: WM_CLOSE message(也检查[MS.Docs]: Closing the Window)。请注意,它是特定的Win!

  • 您已经拥有获取具有特定名称的进程(pids)的代码
  • [SO]: Get the title of a window of another program using the process name (@CristiFati's answer)包含从进程(ids)获取窗口(标题)的代码。实际上它包含更多,但这就是你需要的东西(enumWindowsProc和enumProcWnds函数)
  • 关闭窗口的代码: win32api.SendMessage(0x005C0974, win32con.WM_CLOSE) # 0x005C0974 was Chrome's (main) window handle in my test
  • 你需要做的就是结合以上3(略有变化)

另一个适用于windows的例子:[SO]: Keyboard event not sent to window with pywin32 (@CristiFati's answer)


1
投票

一个更通用的版本,它向应用程序发送关闭消息,包括仅在系统托盘中可见的消息,包含所有必需的导入:

import win32con
import win32api
import win32gui
import win32process
import psutil

def enumWindowsProc(hwnd, lParam):
    if (lParam is None) or ((lParam is not None) and win32process.GetWindowThreadProcessId(hwnd)[1] == lParam):
        text = win32gui.GetWindowText(hwnd)
        if text:
            win32api.SendMessage(hwnd, win32con.WM_CLOSE)

def stop_app(app_exe):
    for process in psutil.process_iter():
        if process.name() == app_exe:
            win32gui.EnumWindows(enumWindowsProc, process.pid)

stop_app("appname.exe")

(基于问题中的“每个CristiFati建议的快速解决方案”,但将'pid'更改为'lParam',包括所需的导入,还适用于仅在系统托盘中可见的应用程序。)

© www.soinside.com 2019 - 2024. All rights reserved.