Python监控Windows程序关闭状态:WMI与WaitForSingleObject方案

Alice
Alice
发布时间:2026-10-13| 5人浏览过
原创

本文介绍在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方法改为以上

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。