python小工具--查看窗口程序進(jìn)程

前言

有一次我服務(wù)器中招了頻繁的彈出重啟對話框并重啟的事情(進(jìn)入安全模式?jīng)]有找到和啟動此命令有關(guān)的程序),我不得不在有限的時間里嘗試找到此進(jìn)程并Kill掉它,使用pchunter和process monitor均沒有在有限的時間內(nèi)找到正確的進(jìn)程,后來發(fā)現(xiàn)好像也沒有類似的小工具,于是絕對自己寫一個。

? windows的朋友都知道對于windows來說最重要的兩個系統(tǒng)API庫就是kernel32.dll和user32.dll,kernel32.dll主要是和內(nèi)核交互我們此時用不到,user32.dll主要是處理windows用戶界面的api庫,正是我們需要的。于是我找到了user32.dll的庫開發(fā)文檔,打算用golang寫一個小工具。

2000 years later...

放棄了,不是windows開發(fā)者,看user32.dll還是短時間存在一定困難,且golang沒有相關(guān)的調(diào)用庫,直接load user32.dll感覺是找麻煩。此時又想起python大法,發(fā)現(xiàn)python最優(yōu)秀的地方就是庫太多了,存在pywin32這么個庫來轉(zhuǎn)接windows的API。

需求

  • 快速開發(fā)一個應(yīng)急小程序,可以鼠標(biāo)點點點查看窗體程序的進(jìn)程號

  • 再快速一點

設(shè)計實現(xiàn)

考慮把大象放冰箱鼠標(biāo)點擊一下就能查看窗體的進(jìn)程號分幾步:

  • 獲取點擊時鼠標(biāo)坐標(biāo)

  • 獲取鼠標(biāo)點擊位置窗口句柄

  • 獲取窗口標(biāo)題的函數(shù)和進(jìn)程號

  • 監(jiān)聽鼠標(biāo)按鍵事件觸發(fā)上述過程

pywin32的函數(shù)命名和user32.dll的庫函數(shù)名字是類似的,于是我直接在pywin32的開發(fā)文檔里面搜索CursorPos發(fā)現(xiàn)存在win32gui.GetCursorPos()函數(shù)獲取鼠標(biāo)坐標(biāo),操作很簡單

from win32 import win32gui
point =win32gui.GetCursorPos()#point為鼠標(biāo)坐標(biāo)

對照User32的開發(fā)文檔和pywin32的開發(fā)文檔搜索出獲取窗口句柄的函數(shù)、窗口標(biāo)題、和窗口進(jìn)程的函數(shù)

from win32 import win32gui,win32process
win32gui.WindowFromPoint()#獲取當(dāng)前窗口句柄
win32gui.GetWindowText()#獲取當(dāng)前窗口標(biāo)題
win32process.GetWindowThreadProcessId() #獲取當(dāng)前窗口進(jìn)程和線程

搜索pywin32關(guān)于mouse和CursorPos,沒有發(fā)現(xiàn)有關(guān)于鼠標(biāo)監(jiān)聽的函數(shù),只搜到win32gui._TrackMouseEvent,我們知道“_”開頭的函數(shù)一般是內(nèi)部函數(shù)能用也不好用。要不怎么說python大法好呢,隨便搜索下得知pynput庫可以監(jiān)聽鼠標(biāo)鍵盤事件,官方Demo代碼足以。

最后實現(xiàn)我們的demo代碼

from win32 import win32gui,win32process
from pynput.mouse import Listener,Button

while True:
    #官方鼠標(biāo)監(jiān)聽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()#獲取鼠標(biāo)坐標(biāo)
        p=win32gui.WindowFromPoint(point)#獲取鼠標(biāo)坐標(biāo)位置窗口句柄
        p_name=win32gui.GetWindowText(p)#獲取窗口句柄對應(yīng)的進(jìn)程名
        _,p_id=win32process.GetWindowThreadProcessId(p)#獲取窗口句柄對應(yīng)的PID
        print(p_name,p_id)

執(zhí)行Python xxx.py 測試沒問題,然而pyinstaller打包失敗,Pynput無法打包成pyd,作為應(yīng)急使用,就不研究為啥打包失敗了,考慮類似win32gui._TrackMouseEvent實現(xiàn),我們可以利用Sleep函數(shù)自己簡單實現(xiàn)鼠標(biāo)懸停效果,都沒10行代碼就解決問題。

from win32 import win32gui,win32process
import time
while True:
    point1 =win32gui.GetCursorPos()#獲取鼠標(biāo)坐標(biāo)
    time.sleep(2)#模擬鼠標(biāo)兩秒懸停
    point2 =win32gui.GetCursorPos()#獲取鼠標(biāo)坐標(biāo)
    if point2 == point1:
        p=win32gui.WindowFromPoint(point2)#獲取鼠標(biāo)坐標(biāo)位置窗口句柄
        p_name=win32gui.GetWindowText(p)#獲取窗口句柄對應(yīng)的進(jìn)程名
        _,p_id=win32process.GetWindowThreadProcessId(p)#獲取窗口句柄對應(yīng)的PID
        print(p_name,p_id)

測試python xxx.py執(zhí)行成功,pyinstaller打包測試成功。

代碼實現(xiàn)

代碼量不多,調(diào)整下格式即可:

#coding=utf-8
#date 2020.12.23
#depand:python3.8,win32
#描述:鼠標(biāo)懸停窗體2秒輸出進(jìn)程名和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()#獲取鼠標(biāo)坐標(biāo)
        time.sleep(2)
        point2 =win32gui.GetCursorPos()#獲取鼠標(biāo)坐標(biāo)
        if point2 == point1:
           get_PID(point2)
if __name__ == "__main__":
    main()
  

使用Pyinstaller打包,打包完大概6.7mb,這也是Python無奈的地方,隨便幾行代碼就這么大,最好還是用編譯語言實現(xiàn),幾十kb就行了。本例中代碼量不多,但是看win32的開發(fā)文檔過程還是蠻痛苦的,希望能給大家提供一些思考問題的思路。Python版最后執(zhí)行效果如下:

1.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容