我一直在尝试确定一种使用Python正常关闭Chrome(及其他进程)的方法。我已经尝试了几种方法,但是所有方法都会导致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()代替各种信号类型的terate()(Windows实际上仅支持三种,CTRL_BREAK_EVENT,CNTL_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)
答案 0 :(得分:2)
显然, Chrome 在由于进程终止而关闭时不满意。它具有检测这种确切情况的机制。
它正在运行许多流程,我认为这可以是一种通过仔细选择流程顺序来正常关闭流程的方法(我可能是错的,但是我记得一旦我做到了)被杀死( crashpad-handler , utility , renderer ,在 master 之前),但是现在我可以不这样做,我也不知道那实际上是多么优雅。
注意:我个人认为此行为非常有用,因为我打开了许多带有许多标签的 Chrome 窗口,并且每次我需要重新启动笔记本电脑时,从任务管理器关闭 Chrome ,以便下次打开它时,它将恢复当前状态。
回到我们的问题,一种方法是获取其窗口并将其发送给[MS.Docs]: WM_CLOSE message(也请检查[MS.Docs]: Closing the Window)。请注意,它特定于 Win !
关闭窗口的代码:
win32api.SendMessage(0x005C0974, win32con.WM_CLOSE) # 0x005C0974 was Chrome's (main) window handle in my test
另一个适用于Windows的示例:[SO]: Keyboard event not sent to window with pywin32 (@CristiFati's answer)。
答案 1 :(得分:1)
一种更通用的版本,用于向应用发送关闭消息,包括仅在系统任务栏中可见的关闭消息,以及所有必需的导入项:
app:popUpTo
(基于“问题”中的“根据CristiFati建议快速解决方案”,但将“ pid”更改为“ lParam”,包括所需的导入,并且还适用于仅在系统任务栏中可见的应用程序。)