写点什么

Python PyWin32 模块

作者:lyshark
  • 2023-02-01
    北京
  • 本文字数:8640 字

    阅读完需:约 28 分钟

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 lyshark14
复制代码


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 win32guiimport 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 win32apiimport win32conb = (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,sysimport win32apiimport win32conimport 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 win32processimport win32apiimport win32confrom 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.comwin32api.ShellExecute(None, "explore", "D:\\C++", None, None, SW_SHOWNORMAL)  # 打开目录D:\C++win32api.ShellExecute(None, "print", "C:\\Test.txt", None, None, SW_HIDE)  # 打印文件C:\Test.txtwin32api.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 timeimport win32guiimport win32apiimport 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 win32apiimport win32guiimport win32conimport win32printimport 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+Fwin32api.keybd_event(18, 0, 0, 0) # Altwin32api.keybd_event(70, 0, 0, 0) # Fwin32api.keybd_event(70, 0, win32con.KEYEVENTF_KEYUP, 0) # 释放按键win32api.keybd_event(18, 0, win32con.KEYEVENTF_KEYUP, 0)
# 3.Messagewin = 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表示执行错误
# 打印 -pdfdef 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, win32conimport 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()) # 获取临时文件夹路径
复制代码


发布于: 刚刚阅读数: 3
用户头像

lyshark

关注

🏆 InfoQ写作平台-签约作者 🏆 2023-01-18 加入

【个人简介】致力于二进制安全,反病毒,算法还原技术研究。 【门户网站】https://www.lyshark.com

评论

发布
暂无评论
Python PyWin32 模块_Python_lyshark_InfoQ写作社区