Python监控Windows程序关闭状态:WMI与WaitForSingleObject方案
本文介绍在Python中监控Windows程序是否关闭的方法。通过对比EnumProcesses和psutil的局限性,提出使用WMI结合WaitForSingleObject的方案。文章详细讲解了如何获取SeDebugPrivilege权限、使用OpenProcess获取句柄,并通过WaitForSingleObject阻塞等待进程结束,相比轮询更高效。
Python监控Windows程序关闭状态概述
本文主要介绍如何利用Python监控Windows程序是否关闭,文中通过示例代码进行了详细解析,对读者的学习或工作具有参考价值。
进程监控方案对比与WMI引入
监控一个exe服务在关闭后打印日志,最初尝试使用win32process.EnumProcesses()获取所有程序PID,再根据PID获取进程名进行对比,以判断程序是否关闭。但遇到一个问题:无法直接根据PID获取进程名,除非使用psutil包,但这会使程序变得过于臃肿。随后尝试查找C++示例寻求灵感,然而C++的API函数在Python中并不直接存在,以往遇到此类问题通常使用wmi解决。
import wmi
c = wmi.WMI()
for process in c.Win32_Process():
print process.ProcessId, process.Name
但WMI的速度出奇地慢,实在不适合高性能场景。
最后在外网找到一个示例,可以很好地解决该问题。
from win32com.client import GetObject
_wmi = GetObject('winmgmts:')
# collect all the running processes
processes = _wmi.ExecQuery('Select * from win32_process')
for p in processes:
print((p.ProcessId, p.ExecutablePath, p.CommandLine, p.Name))
由此全部代码为
核心实现:权限获取与句柄等待
def wmi_sql_all_name(pname):#全部程序列表
from win32com.client import GetObject
_wmi = GetObject('winmgmts:')
processes = _wmi.ExecQuery('Select * from win32_process')
for p in processes:
if p.name==pname:
return p.ProcessId
def process_restat(pname):
import win32security, win32event#-----------------------------------------获取令牌
hToken = win32security.OpenProcessToken(win32api.GetCurrentProcess(),
win32con.TOKEN_ADJUST_PRIVILEGES | win32con.TOKEN_QUERY) # 打开自己的程序令牌
luid = win32security.LookupPrivilegeValue(None, 'SeDebugPrivilege') # 查看自己的权限,并写入权限关键字
PyTOKEN = ((luid, win32con.SE_PRIVILEGE_ENABLED),) # 将这些做成序列用做参数
pyt1 = win32security.AdjustTokenPrivileges(hToken, 0, PyTOKEN) # 权限写入#----------------------------------------
processid=wmi_sql_all_name(pname)
if processid!= None:
hprocess = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, processid)
win32event.WaitForSingleObject(hprocess, -1)
win32api.CloseHandle(hprocess)
print U'已关闭'
else:
print u'未启动'
首先需要获取令牌,否则获取很多服务或者系统进程的信息都会报权限不足
使用OpenProcess得到程序句柄,
使用WaitForSingleObject得到程序的已通知状态也就是运行状态,第二参数为等待时间 -1 为永久等待
注意该函数会死锁线程,但不会占用CPU,很适合丢在子线程里,比无限循环跑程序列表要有效率得多
-------------------
突然想到有SQL语句了 我为啥还要循环呢?
优化:利用WMI SQL查询简化逻辑
def wmi_sql_all_name(pname):
from win32com.client import GetObject
_wmi = GetObject('winmgmts:')
processes = _wmi.ExecQuery("Select * from win32_process where name= '%s'"%(pname))
try:
return processes[0].ProcessId
except:
print u"没有发现程序"
return None
将wmi_sql_all_name方法改为以上
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













