检查 Windows 上某个进程是否正在运行?
- 2025-03-06 08:55:00
- admin 原创
- 68
问题描述:
我正在尝试创建一个 Python 脚本,稍后我会将其作为服务运行。现在我想仅在 iTunes 运行时运行代码的特定部分。我从一些研究中了解到,轮询整个命令列表然后搜索该列表的应用程序是昂贵的。
我发现基于 UNIX 的操作系统上的进程会创建一个锁文件来通知程序当前正在运行,此时我们可以使用它os.stat(location_of_file)
来检查该文件是否存在来确定程序是否正在运行。
Windows 上是否创建了类似的锁文件?
如果不是,在 Python 中我们可以用哪些方法来判断某个进程是否正在运行?
我正在使用 python 2.7 和 iTunes COM 接口。
解决方案 1:
您不能依赖 Linux 或 Windows 中的锁定文件。我只能咬紧牙关,遍历所有正在运行的程序。我真的不相信它会像您想象的那样“昂贵”。psutil 是一个出色的跨平台 Python 模块,可以枚举系统上所有正在运行的程序。
import psutil
"someProgram" in (p.name() for p in psutil.process_iter())
解决方案 2:
尽管 @zeller 已经说过了,但这里有一个如何使用的示例tasklist
。因为我只是在寻找vanilla python 替代品...
import subprocess
def process_exists(process_name):
call = 'TASKLIST', '/FI', 'imagename eq %s' % process_name
# use buildin check_output right away
output = subprocess.check_output(call).decode()
# check in last line for process name
last_line = output.strip().split('
')[-1]
# because Fail message could be translated
return last_line.lower().startswith(process_name.lower())
现在你可以这样做:
>>> process_exists('eclipse.exe')
True
>>> process_exists('AJKGVSJGSCSeclipse.exe')
False
为了避免多次调用此方法并以此方式概览所有流程,您可以执行以下操作:
# get info dict about all running processes
import subprocess
output = subprocess.check_output(('TASKLIST', '/FO', 'CSV')).decode()
# get rid of extra " and split into lines
output = output.replace('"', '').split('
')
keys = output[0].split(',')
proc_list = [i.split(',') for i in output[1:] if i]
# make dict with proc names as keys and dicts with the extra nfo as values
proc_dict = dict((i[0], dict(zip(keys[1:], i[1:]))) for i in proc_list)
for name, values in sorted(proc_dict.items(), key=lambda x: x[0].lower()):
print('%s: %s' % (name, values))
解决方案 3:
win32ui.FindWindow(classname, None)
如果找到具有给定类名的任何窗口,则返回窗口句柄。window32ui.error
否则,它会引发。
import win32ui
def WindowExists(classname):
try:
win32ui.FindWindow(classname, None)
except win32ui.error:
return False
else:
return True
if WindowExists("DropboxTrayIcon"):
print "Dropbox is running, sir."
else:
print "Dropbox is running..... not."
我使用 Autohotkey Window Spy 发现 Dropbox 托盘图标的窗口类名称是 DropboxTrayIcon。
参见
MSDN 查找窗口
解决方案 4:
试试这个代码:
import subprocess
def process_exists(process_name):
progs = str(subprocess.check_output('tasklist'))
if process_name in progs:
return True
else:
return False
检查该进程是否正在运行:
if process_exists('example.exe'):
#do something
解决方案 5:
Windows 上通常不使用锁定文件(Unix 上也很少使用)。通常,当 Windows 程序想要查看其自身的另一个实例是否已在运行时,它会FindWindow
使用已知标题或类名进行调用。
def iTunesRunning():
import win32ui
# may need FindWindow("iTunes", None) or FindWindow(None, "iTunes")
# or something similar
if FindWindow("iTunes", "iTunes"):
print "Found an iTunes window"
return True
解决方案 6:
我想将此解决方案添加到列表中,以供历史参考。它允许您根据 .exe 而不是窗口标题查找,并返回使用的内存和 PID。
processes = subprocess.Popen('tasklist', stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0]
# Put a regex for exact matches, or a simple 'in' for naive matches
示例输出的一部分:
notepad.exe 13944 Console 1 11,920 K
python.exe 5240 Console 1 28,616 K
conhost.exe 9796 Console 1 7,812 K
svchost.exe 1052 Services 0 18,524 K
iTunes.exe 1108 Console 1 157,764 K
解决方案 7:
import psutil
for p in psutil.process_iter(attrs=['pid', 'name']):
if "itunes.exe" in (p.info['name']).lower():
print("yes", (p.info['name']).lower())
对于 Python 3.7
import psutil
for p in psutil.process_iter(attrs=['pid', 'name']):
if p.info['name'] == "itunes.exe":
print("yes", (p.info['name']))
这适用于 python 3.8 和 psutil 5.7.0、windows
解决方案 8:
Mark 建议的 Psutil确实是最佳解决方案,它的唯一缺点是 GPL 兼容许可证。如果这是个问题,那么您可以调用 Windows 的进程信息命令:wmic process
WMI 可用的位置(XP pro、vista、win7)或tasklist
。以下是执行此操作的说明:如何在 python 中调用外部程序并检索输出和返回代码?(不是唯一可能的方法……)
解决方案 9:
根据每个人的帖子:https://stackoverflow.com/a/29275361/7530957
可能会出现多个问题:
多个进程同名
长进程的名称
如果进程名称很长,‘everybody’s 代码将无法工作。因此,此行存在问题:
last_line.lower().startswith(process_name.lower())
因为last_line会比进程名称短。
因此,如果您只想知道某个进程/进程是否处于活动状态:
from subprocess import check_output
def process_exists(process_name):
call = 'TASKLIST', '/FI', 'imagename eq %s' % process_name
if check_output(call).splitlines()[3:]:
return True
而是获取一个或多个进程的所有信息
from subprocess import check_output
def process_exists(process_name):
call = 'TASKLIST', '/FI', 'imagename eq %s' % process_name
processes = []
for process in check_output(call).splitlines()[3:]:
process = process.decode()
processes.append(process.split())
return processes
解决方案 10:
您是否乐意使用 Python 命令运行另一个程序来获取信息?
如果是这样,我建议您查看PsList及其所有选项。例如,以下内容将告诉您有关任何正在运行的 iTunes 进程的信息
PsList itunes
如果您能弄清楚如何解释结果,这应该会对您有所帮助。
编辑:
当我没有运行 iTunes 时,我得到以下信息:
pslist v1.29 - Sysinternals PsList
Copyright (C) 2000-2009 Mark Russinovich
Sysinternals
Process information for CLARESPC:
Name Pid Pri Thd Hnd Priv CPU Time Elapsed Time
iTunesHelper 3784 8 10 229 3164 0:00:00.046 3:41:05.053
在运行 iTunes 时,我得到了以下一行:
iTunes 928 8 24 813 106168 0:00:08.734 0:02:08.672
但是,以下命令仅打印出有关 iTunes 程序本身的信息,即使用以下-e
参数:
pslist -e itunes
解决方案 11:
如果不能依赖进程名称,例如 python 脚本,其进程名称始终为 python.exe。如果发现此方法非常方便
import psutil
psutil.pid_exists(pid)
查看文档以获取更多信息
http://psutil.readthedocs.io/en/latest/#psutil.pid_exists
解决方案 12:
有一个名为 wmi 的 Python 模块。
import wmi
c=wmi.WMI()
def check_process_running(str_):
if(c.Win32_Process(name=str_)):
print("Process is running")
else:
print("Process is not running")
check_process_running("yourprocess.exe")
解决方案 13:
我喜欢@ewerybody 的解决方案,并做了一些小小的改动
import subprocess
def process_exists(process_name):
call = 'TASKLIST', '/FI', 'imagename eq %s' % process_name
# use buildin check_output right away
output = subprocess.check_output(call).decode()
# check in last line for process name
last_line = output.split('
')
#first result is 3 because the headers
#or in case more than one, you can use the last one using [-2] index
data = " ".join(last_line[3].split()).split()
#return a list with the name and pid
return( [data[0], data[1]] )
解决方案 14:
下面的方法可以用来检测进程[例如:notepad.exe]是否正在运行。
from pymem import Pymem
import pymem
while (True):
try:
pm = Pymem('notepad.exe')
print('Notepad Started And Is Running....')
except:
print ('Notepad Is Not Running....')
需要 Pymem 包。要安装它,
pip install pymem
解决方案 15:
我发现 psutil 非常慢。一个性能更好的解决方案:
import win32gui
window_titles = set()
def winEnumHandler( hwnd, ctx ):
if win32gui.IsWindowVisible( hwnd ):
window_titles.add(win32gui.GetWindowText( hwnd ) )
win32gui.EnumWindows( winEnumHandler, None )
print(window_titles)
解决方案 16:
效果很好
def running():
n=0# number of instances of the program running
prog=[line.split() for line in subprocess.check_output("tasklist").splitlines()]
[prog.pop(e) for e in [0,1,2]] #useless
for task in prog:
if task[0]=="itunes.exe":
n=n+1
if n>0:
return True
else:
return False
解决方案 17:
如果你正在使用 Behave 测试应用程序,则可以使用pywinauto
。与之前的评论类似,你可以使用此功能:
def check_if_app_is_running(context, processName):
try:
context.controller = pywinauto.Application(backend='uia').connect(best_match = processName, timeout = 5)
context.controller.top_window().set_focus()
return True
except pywinauto.application.ProcessNotFoundError:
pass
return False
backend
可以是“uia”或“win32”
timeout
如果在 5 秒内强制重新连接应用程序。
解决方案 18:
import subprocess as sp
for v in str(sp.check_output('powershell "gps | where {$_.MainWindowTitle}"')).split(' '):
if len(v) is not 0 and '-' not in v and '\\r\\' not in v and 'iTunes' in v: print('Found !')
解决方案 19:
import psutil
def check_process_status(process_name):
"""
Return status of process based on process name.
"""
process_status = [ proc.status() for proc in psutil.process_iter() if proc.name() == process_name ]
if process_status:
print("Process name %s and staus %s"%(process_name, process_status[0]))
else:
print("Process name not valid", process_name)
解决方案 20:
Psutil
是最好的解决方案。
import psutil
processes = list(p.name() for p in psutil.process_iter())
# print(processes)
count = processes.count("<app_name>.exe")
if count == 1:
logging.info('Application started')
# print('Application started')
else:
logging.info('Process is already running!')
# print('Process is already running!')
sys.exit(0) # Stops duplicate instance from running
解决方案 21:
您可以只os.kill
发送 0 信号(不会终止进程)并检查错误。
from os import kill
def check_if_running(pid):
try:
kill(pid, 0)
except:
return False
return True
解决方案 22:
if tasklist.find("chrome.exe") > 0:
os.system("taskkill /im chrome.exe") # kill if it is running.
扫码咨询,免费领取项目管理大礼包!