python小工具--查看窗口程序进程
前言
有一次我服务器中招了频繁的弹出重启对话框并重启的事情(进入安全模式没有找到和启动此命令有关的程序),我不得不在有限的时间里尝试找到此进程并Kill掉它,使用pchunter和process monitor均没有在有限的时间内找到正确的进程,后来发现好像也没有类似的小工具,于是绝对自己写一个。
windows的朋友都知道对于windows来说最重要的两个系统API库就是kernel32.dll和user32.dll,kernel32.dll主要是和内核交互我们此时用不到,user32.dll主要是处理windows用户界面的api库,正是我们需要的。于是我找到了user32.dll的库开发文档,打算用golang写一个小工具。
2000 years later...
放弃了,不是windows开发者,看user32.dll还是短时间存在一定困难,且golang没有相关的调用库,直接load user32.dll感觉是找麻烦。此时又想起python大法,发现python最优秀的地方就是库太多了,存在pywin32这么个库来转接windows的API。
需求
-
快速开发一个应急小程序,可以鼠标点点点查看窗体程序的进程号
-
再快速一点
设计实现
考虑把大象放冰箱鼠标点击一下就能查看窗体的进程号分几步:
-
获取点击时鼠标坐标
-
获取鼠标点击位置窗口句柄
-
获取窗口标题的函数和进程号
-
监听鼠标按键事件触发上述过程
pywin32的函数命名和user32.dll的库函数名字是类似的,于是我直接在pywin32的开发文档里面搜索CursorPos发现存在win32gui.GetCursorPos()函数获取鼠标坐标,操作很简单
from win32 import win32gui
point =win32gui.GetCursorPos()#point为鼠标坐标
对照User32的开发文档和pywin32的开发文档搜索出获取窗口句柄的函数、窗口标题、和窗口进程的函数
from win32 import win32gui,win32process
win32gui.WindowFromPoint()#获取当前窗口句柄
win32gui.GetWindowText()#获取当前窗口标题
win32process.GetWindowThreadProcessId() #获取当前窗口进程和线程
搜索pywin32关于mouse和CursorPos,没有发现有关于鼠标监听的函数,只搜到win32gui._TrackMouseEvent,我们知道“_”开头的函数一般是内部函数能用也不好用。要不怎么说python大法好呢,随便搜索下得知pynput库可以监听鼠标键盘事件,官方Demo代码足以。
最后实现我们的demo代码
from win32 import win32gui,win32process
from pynput.mouse import Listener,Button
while True:
#官方鼠标监听Demo代码
def on_click(x, y,button,pressed):
if not pressed:
return False
with Listener( on_click=on_click,on_scroll=on_scroll) as listener:
listener.join()
point =win32gui.GetCursorPos()#获取鼠标坐标
p=win32gui.WindowFromPoint(point)#获取鼠标坐标位置窗口句柄
p_name=win32gui.GetWindowText(p)#获取窗口句柄对应的进程名
_,p_id=win32process.GetWindowThreadProcessId(p)#获取窗口句柄对应的PID
print(p_name,p_id)
执行Python xxx.py 测试没问题,然而pyinstaller打包失败,Pynput无法打包成pyd,作为应急使用,就不研究为啥打包失败了,考虑类似win32gui._TrackMouseEvent实现,我们可以利用Sleep函数自己简单实现鼠标悬停效果,都没10行代码就解决问题。
from win32 import win32gui,win32process
import time
while True:
point1 =win32gui.GetCursorPos()#获取鼠标坐标
time.sleep(2)#模拟鼠标两秒悬停
point2 =win32gui.GetCursorPos()#获取鼠标坐标
if point2 == point1:
p=win32gui.WindowFromPoint(point2)#获取鼠标坐标位置窗口句柄
p_name=win32gui.GetWindowText(p)#获取窗口句柄对应的进程名
_,p_id=win32process.GetWindowThreadProcessId(p)#获取窗口句柄对应的PID
print(p_name,p_id)
测试python xxx.py执行成功,pyinstaller打包测试成功。
代码实现
代码量不多,调整下格式即可:
#coding=utf-8
#date 2020.12.23
#depand:python3.8,win32
#描述:鼠标悬停窗体2秒输出进程名和PID
from win32 import win32gui,win32process
import time
import sys
def get_PID(point):
try:
p=win32gui.WindowFromPoint(point)
p_name=win32gui.GetWindowText(p)
_,p_id=win32process.GetWindowThreadProcessId(p)
print(p_name,p_id)
except:
print("win32获取窗体信息失败 error")
sys.exit(1)
def main():
while True:
point1 =win32gui.GetCursorPos()#获取鼠标坐标
time.sleep(2)
point2 =win32gui.GetCursorPos()#获取鼠标坐标
if point2 == point1:
get_PID(point2)
if __name__ == "__main__":
main()
使用Pyinstaller打包,打包完大概6.7mb,这也是Python无奈的地方,随便几行代码就这么大,最好还是用编译语言实现,几十kb就行了。本例中代码量不多,但是看win32的开发文档过程还是蛮痛苦的,希望能给大家提供一些思考问题的思路。Python版最后执行效果如下:
1.jpg