Python的生產效率極高,通過使用pypiwin32模塊可以快速調用windows API函數,結合Python的高效開發能力,同等時間內比C++能更快的達到目標,pypiwin32模塊封裝了Win32下的常用定義,函數方法等。
該項目地址是:https://github.com/mhammond/pywin32
在Python安裝路徑下\AppData\Local\Programs\Python\Python38\Lib\site-packages 有幫助文檔:PyWin32.chm
文件類API在模塊win32file中,進程類API在模塊win32process中,win32con定義了所有的常量,,一些難以分類的API則在模塊win32api中(大部分是kernel32.dll導出的API)
ctypes 調用C庫printf打印輸出
>>> import ctypes
>>> # cdll = cdecl標准 windll = stdcall標准 linux則是調用 libc.so.6
>>> msvcrt = ctypes.cdll.LoadLibrary("C:\WINDOWS\system32\msvcrt.dll")
>>> msvcrt = ctypes.cdll.msvcrt
>>>
>>> string = "hello lyshark\n"
>>> string = string.encode("utf-8")
>>> msvcrt.printf(string)
hello lyshark
14
ctypes 調用messagebox輸出:
>>> from ctypes import *
>>> user32 = windll.LoadLibrary("user32.dll")
>>> string = "Hello lyshark\n"
>>> string = string.encode("utf-8")
>>>
>>>user32.MessageBoxA(0,string,"ctypes".encode("utf-8"),0)
>>>
>>>user32 = windll.LoadLibrary("user32.dll")
>>>MessageBox = user32.MessageBoxA
>>>print(MessageBox(0,"hello lyshark".encode("utf-8"),"msgbox".encode("utf-8"),0))
ctypes 調用 kernel32
>>> kernel32 = windll.LoadLibrary("kernel32.dll")
>>> CreateProcess = kernel32.CreateProcessA
>>> ReadProcessMemory = kernel32.ReadProcessMemory
ctypes 聲明結構體
from ctypes import *
class MyStruct(Structure):
_fields_ = [
("username",c_char*10),
("age",c_int),
("sex",c_long)
]
class MyUnion(Union):
_fields_ = [
("a_long",c_long),
("a_int",c_int),
("a_char",c_char*10)
]
MyStruct.username = "lyshark"
MyStruct.age = 22
print(MyStruct.username)
pywin32常用使用方式
>>> import win32api
>>> import win32con
>>>
>>> win32api.MessageBox(0,"hello lyshark","Msgbox",win32con.MB_OK)
1
>>> import win32process
# 打開記事本程序,獲得其句柄
>>> handle = win32process.CreateProcess('c:\\windows\\notepad.exe',
'', None , None , 0 ,win32process. CREATE_NO_WINDOW , None , None ,
win32process.STARTUPINFO())
# 使用TerminateProcess函數終止記事本程序
>>> win32process.TerminateProcess(handle[0],0)
>>> import win32event
# 創建進程獲得句柄
>>> handle = win32process.CreateProcess('c:\\windows\\notepad.exe',
'', None , None , 0 ,win32process. CREATE_NO_WINDOW , None , None ,
win32process.STARTUPINFO())
# 等待進程結束
>>> win32event.WaitForSingleObject(handle[0], -1)
0 # 進程結束的返回值
>>> import win32api
# 打開記事本程序,在后台運行,即顯示記事本程序的窗口
>>> win32api.ShellExecute(0, 'open', 'notepad.exe', '','',0)
鼠標控制
import win32gui
import win32api
獲取句柄
hwnd = win32gui.FindWindow(classname, titlename)
獲取窗口左上角和右下角坐標
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
獲取某個句柄的類名和標題
title = win32gui.GetWindowText(hwnd)
clsname = win32gui.GetClassName(hwnd)
獲取父句柄hwnd類名為clsname的子句柄
hwnd1= win32gui.FindWindowEx(hwnd, None, clsname, None)
獲取位置
win32api.GetCursorPos()
鼠標定位到(30,50)
win32api.SetCursorPos([30,150])
執行左單鍵擊,若需要雙擊則延時幾毫秒再點擊一次即可
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP | win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
右鍵單擊
win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP | win32con.MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
發送回車鍵
win32api.keybd_event(13,0,0,0)
win32api.keybd_event(13,0,win32con.KEYEVENTF_KEYUP,0)
關閉窗口
win32gui.PostMessage(win32lib.findWindow(classname, titlename), win32con.WM_CLOSE, 0, 0)
鼠標左右鍵判斷
import win32api
import win32con
b = (0,0)
# win32api.GetAsyncKeyState(win32con.VK_LMENU)
# VK_LBUTTON 鼠標左鍵
# VK_RBUTTON 鼠標右鍵
# https://baike.baidu.com/item/GetAsyncKeyState/918387?fr=aladdin
for i in range(100):
a = win32api.GetCursorPos()
if a != b:
b = a
print(a)
else:
print("xx")
time.sleep(1)
將上面代碼有趣的組合在一起,可以搞事情了,部分片段。
def Write_Dictionaries(LogName,Dict):
logging.basicConfig(level=logging.DEBUG,
format = "%(asctime)s --> %(message)s",
datefmt = "%Y-%m-%d %H:%M:%S",
filename = LogName,
filemode = "a+")
logging.info(str(Dict))
def RecordingScript(LogName,Sleep):
temp = (0,0)
mose = {"Pos_x":0, "Pos_y":0, "MouseL":0, "MouseR":0}
while True:
Position = win32api.GetCursorPos()
MouseLeft = win32api.GetAsyncKeyState(win32con.VK_LBUTTON)
MouseRight = win32api.GetAsyncKeyState(win32con.VK_RBUTTON)
if Position != temp or MouseLeft!=0 or MouseRight!=0:
temp = Position
mose["Pos_x"] = Position[0]
mose["Pos_y"] = Position[1]
mose["MouseL"] = MouseLeft
mose["MouseR"] = MouseRight
Write_Dictionaries(LogName,mose)
time.sleep(int(Sleep))
def writelog():
with open("aaa.log","r",encoding="utf-8") as fp:
b = [ item.split(" --> ")[1] for item in fp.readlines()]
for i in b:
dic = eval(i.replace("\n",""))
win32api.SetCursorPos(bos)
print("坐標:{}".format(bos))

遍歷進程模塊: 便利進程的模塊
import os,sys
import win32api
import win32con
import win32process
handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid ===> 10992 )
hModule = win32process.EnumProcessModules(handle)
temp=[]
for i in hModule:
print(win32process.GetModuleFileNameEx(handle,i))
win32api.CloseHandle(handle)
調用createprocess:
CreateProcess調用
appName:可執行的文件名。
commandLine:命令行參數。
processAttributes:進程安全屬性,如果為None,則為默認的安全屬性。
threadAttributes:線程安全屬性,如果為None,則為默認的安全屬性。
bInheritHandles:繼承標志。
dwCreationFlags:創建標志。
newEnvironment:創建進程的環境變量。
currentDirectory:進程的當前目錄。
startupinfo :創建進程的屬性。
WaitForSingleObject(handle, milisecond)
handle : 要操作的進程句柄
milisecond: 等待的時間,如果為-1,則一直等待.
>>> import win32process
>>> handle=win32process.CreateProcess("d://run.exe", '', None , None , 0 ,win32process.CREATE_NEW_CONSOLE , None , None ,win32process.STARTUPINFO())
>>> win32event.WaitForSingleObject(handle[0],2)
枚舉部分進程模塊
import win32process
import win32api
import win32con
from ctypes import *
import ctypes
def GetProcessModules( pid ):
handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid )
hModule = win32process.EnumProcessModules(handle)
temp=[]
for i in hModule:
temp.append([hex(i),win32process.GetModuleFileNameEx(handle,i)])
win32api.CloseHandle(handle)
return temp
temp = GetProcessModules(5852)
for x in temp:
print("[+] 模塊地址: {} ------> 模塊名稱: {}".format(x[0],x[1]))
取出進程PID
handle = win32gui.FindWindow(0,ClassName)
threadpid, procpid = win32process.GetWindowThreadProcessId(handle)
ProcessModule = GetProcessModules(int(procpid))
枚舉所有窗口句柄
import win32gui
hwnd_title = dict()
def get_all_hwnd(hwnd,mouse):
if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd):
hwnd_title.update({hwnd:win32gui.GetWindowText(hwnd)})
win32gui.EnumWindows(get_all_hwnd, 0)
for h,t in hwnd_title.items():
print(h, t)
shellexec 打開網頁或文件
win32api.ShellExecute(None, "open", "C:\\Test.txt", None, None, SW_SHOWNORMAL) # 打開C:\Test.txt 文件
win32api.ShellExecute(None, "open", "http:#www.google.com", None, None, SW_SHOWNORMAL) # 打開網頁www.google.com
win32api.ShellExecute(None, "explore", "D:\\C++", None, None, SW_SHOWNORMAL) # 打開目錄D:\C++
win32api.ShellExecute(None, "print", "C:\\Test.txt", None, None, SW_HIDE) # 打印文件C:\Test.txt
win32api.ShellExecute(None,"open", "mailto:", None, None, SW_SHOWNORMAL) # 打開郵箱
win32api.ShellExecute(None, "open", "calc.exe", None, None, SW_SHOWNORMAL) # 調用計算器
win32api.ShellExecute(None, "open", "NOTEPAD.EXE", None, None, SW_SHOWNORMAL) # 調用記事本
窗口句柄操作: 代碼來自:https://zhuanlan.zhihu.com/p/76168918
import time
import win32gui
import win32api
import win32con
"""
該類實現了:查找(定位)句柄信息,菜單信息
"""
class HandleMenu(object):
def __init__(self, cls_name=None, title=None):
self.handle = win32gui.FindWindow(cls_name, title)
self.window_list = []
def call_back(self, sub_handle, sub_handles): # Edit 20de0
"""遍歷子窗體"""
title = win32gui.GetWindowText(sub_handle)
cls_name = win32gui.GetClassName(sub_handle)
print(title, '+', cls_name)
position = win32gui.GetWindowRect(sub_handle)
aim_point = round(position[0] + (position[2] - position[0]) / 2), round(
position[1] + (position[3] - position[1]) / 2)
win32api.SetCursorPos(aim_point)
time.sleep(1)
# 鼠標點擊
# win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)
# time.sleep(0.05)
# win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)
# time.sleep(0.05)
# ComboBox - ---------
# Edit - ---------
if cls_name == 'ComboBox':
win32gui.SendMessage(sub_handle, win32con.WM_SETTEXT, None, '902723')
time.sleep(1)
sub_handles.append({'cls_name': cls_name, 'title': title})
return True
def get_sub_handles(self):
"""通過父句柄獲取子句柄"""
sub_handles = []
win32gui.EnumChildWindows(self.handle, self.call_back, sub_handles)
print(sub_handles)
return sub_handles
def get_menu_text(self, menu, idx):
import win32gui_struct
mii, extra = win32gui_struct.EmptyMENUITEMINFO() # 新建一個win32gui的空的結構體mii
win32gui.GetMenuItemInfo(menu, idx, True, mii) # 將子菜單內容獲取到mii
ftype, fstate, wid, hsubmenu, hbmpchecked, hbmpunchecked, \
dwitemdata, text, hbmpitem = win32gui_struct.UnpackMENUITEMINFO(mii) # 解包mii
return text
def get_menu(self):
"""menu操作(記事本)"""
menu = win32gui.GetMenu(self.handle)
menu1 = win32gui.GetSubMenu(menu, 0) # 第幾個菜單 0-第一個
cmd_ID = win32gui.GetMenuItemID(menu1, 3) # 第幾個子菜單
win32gui.PostMessage(self.handle, win32con.WM_COMMAND, cmd_ID, 0)
menu_text1 = [self.get_menu_text(menu, i) for i in range(5)]
menu_text2 = [self.get_menu_text(menu1, i) for i in range(9)]
print(menu_text1)
print(menu_text2)
def get_all_window_info(self, hwnd, nouse):
# 去掉下面這句就所有都輸出了,但是我不需要那么多
if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd):
# 設置為最前窗口
win32gui.SetForegroundWindow(hwnd)
# 獲取某個句柄的標題和類名
title = win32gui.GetWindowText(hwnd)
cls_name = win32gui.GetClassName(hwnd)
d = {'類名': cls_name, '標題': title}
info = win32gui.GetWindowRect(hwnd)
aim_point = round(info[0] + (info[2] - info[0]) / 2), round(info[1] + (info[3] - info[1]) / 2)
win32api.SetCursorPos(aim_point)
time.sleep(2)
self.window_list.append(d)
def get_all_windows(self):
"""獲取所有活動窗口的類名、標題"""
win32gui.EnumWindows(self.get_all_window_info, 0)
return self.window_list
if __name__ == '__main__':
# 1.通過父句柄獲取子句柄
# hm=HandleMenu(title='另存為')
# hm.get_sub_handles()
# 2.menu操作
# hm=HandleMenu(title='aa - 記事本')
# hm.get_menu()
# 3.獲取所有活動窗口的類名、標題
hm = HandleMenu()
hm.get_all_windows()
鼠標操作 :
import win32api
import win32gui
import win32con
import win32print
import time
# 1 獲取句柄
# 1.1 通過坐標獲取窗口句柄
handle = win32gui.WindowFromPoint(win32api.GetCursorPos()) # (259, 185)
# 1.2 獲取最前窗口句柄
handle = win32gui.GetForegroundWindow()
# 1.3 通過類名或查標題找窗口
handle = win32gui.FindWindow('cls_name', "title")
# 1.4 找子窗體
sub_handle = win32gui.FindWindowEx(handle, None, 'Edit', None) # 子窗口類名叫“Edit”
# 句柄操作
title = win32gui.GetWindowText(handle)
cls_name = win32gui.GetClassName(handle)
print({'類名': cls_name, '標題': title})
# 獲取窗口位置
info = win32gui.GetWindowRect(handle)
# 設置為最前窗口
win32gui.SetForegroundWindow(handle)
# 2.按鍵-看鍵盤碼
# 獲取鼠標當前位置的坐標
cursor_pos = win32api.GetCursorPos()
# 將鼠標移動到坐標處
win32api.SetCursorPos((200, 200))
# 回車
win32api.keybd_event(13, 0, win32con.KEYEVENTF_EXTENDEDKEY, 0)
win32api.keybd_event(13, 0, win32con.KEYEVENTF_KEYUP, 0)
# 左單鍵擊
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP | win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
# 右鍵單擊
win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP | win32con.MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
# 鼠標左鍵按下-放開
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
# 鼠標右鍵按下-放開
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
# TAB鍵
win32api.keybd_event(win32con.VK_TAB, 0, 0, 0)
win32api.keybd_event(win32con.VK_TAB, 0, win32con.KEYEVENTF_KEYUP, 0)
# 快捷鍵Alt+F
win32api.keybd_event(18, 0, 0, 0) # Alt
win32api.keybd_event(70, 0, 0, 0) # F
win32api.keybd_event(70, 0, win32con.KEYEVENTF_KEYUP, 0) # 釋放按鍵
win32api.keybd_event(18, 0, win32con.KEYEVENTF_KEYUP, 0)
# 3.Message
win = win32gui.FindWindow('Notepad', None)
tid = win32gui.FindWindowEx(win, None, 'Edit', None)
# 輸入文本
win32gui.SendMessage(tid, win32con.WM_SETTEXT, None, '你好hello word!')
# 確定
win32gui.SendMessage(handle, win32con.WM_COMMAND, 1, btnhld)
# 關閉窗口
win32gui.PostMessage(win32gui.FindWindow('Notepad', None), win32con.WM_CLOSE, 0, 0)
# 回車
win32gui.PostMessage(tid, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0) # 插入一個回車符,post 沒有返回值,執行完馬上返回
win32gui.PostMessage(tid, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
print("%x" % win)
print("%x" % tid)
# 選項框
res = win32api.MessageBox(None, "Hello Pywin32", "pywin32", win32con.MB_YESNOCANCEL)
print(res)
win32api.MessageBox(0, "Hello PYwin32", "MessageBox", win32con.MB_OK | win32con.MB_ICONWARNING) # 加警告標志
針對PDF處理:
from win32con import SW_HIDE, SW_SHOWNORMAL
for fn in ['2.txt', '3.txt']:
print(fn)
res = win32api.ShellExecute(0, # 指定父窗口句柄
'print', # 指定動作, 譬如: open、print、edit、explore、find
fn, # 指定要打開的文件或程序
win32print.GetDefaultPrinter(),
# 給要打開的程序指定參數;GetDefaultPrinter 取得默認打印機名稱 <type 'str'>,GetDefaultPrinterW 取得默認打印機名稱 <type 'unicode'>
"./downloads/", # 目錄路徑
SW_SHOWNORMAL) # 打開選項,SW_HIDE = 0; {隱藏},SW_SHOWNORMAL = 1; {用最近的大小和位置顯示, 激活}
print(res) # 返回值大於32表示執行成功,返回值小於32表示執行錯誤
# 打印 -pdf
def print_pdf(pdf_file_name):
"""
靜默打印pdf
:param pdf_file_name:
:return:
"""
# GSPRINT_PATH = resource_path + 'GSPRINT\\gsprint'
GHOSTSCRIPT_PATH = resource_path + 'GHOSTSCRIPT\\bin\\gswin32c' # gswin32c.exe
currentprinter = config.printerName # "printerName":"FUJI XEROX ApeosPort-VI C3370\""
currentprinter = win32print.GetDefaultPrinter()
arg = '-dPrinted ' \
'-dBATCH ' \
'-dNOPAUSE ' \
'-dNOSAFER ' \
'-dFitPage ' \
'-dNORANGEPAGESIZE ' \
'-q ' \
'-dNumCopies=1 ' \
'-sDEVICE=mswinpr2 ' \
'-sOutputFile="\\\\spool\\' \
+ currentprinter + " " + \
pdf_file_name
log.info(arg)
win32api.ShellExecute(
0,
'open',
GHOSTSCRIPT_PATH,
arg,
".",
0
)
# os.remove(pdf_file_name)
截屏:
from PIL import ImageGrab
# 利用PIL截屏
im = ImageGrab.grab()
im.save('aa.jpg')
# 5.文件的讀寫
import win32file, win32api, win32con
import os
def SimpleFileDemo():
testName = os.path.join(win32api.GetTempPath(), "opt_win_file.txt")
if os.path.exists(testName):
os.unlink(testName) # os.unlink() 方法用於刪除文件,如果文件是一個目錄則返回一個錯誤。
# 寫
handle = win32file.CreateFile(testName,
win32file.GENERIC_WRITE,
0,
None,
win32con.CREATE_NEW,
0,
None)
test_data = "Hello\0there".encode("ascii")
win32file.WriteFile(handle, test_data)
handle.Close()
# 讀
handle = win32file.CreateFile(testName, win32file.GENERIC_READ, 0, None, win32con.OPEN_EXISTING, 0, None)
rc, data = win32file.ReadFile(handle, 1024)
handle.Close() # 此處也可使用win32file.CloseHandle(handle)來關閉句柄
if data == test_data:
print("Successfully wrote and read a file")
else:
raise Exception("Got different data back???")
os.unlink(testName)
if __name__ == '__main__':
SimpleFileDemo()
# print(win32api.GetTempPath()) # 獲取臨時文件夾路徑
