pywin32库 : Python 操作 windows 系统 API 您所在的位置:网站首页 python系统库函数find pywin32库 : Python 操作 windows 系统 API

pywin32库 : Python 操作 windows 系统 API

2024-06-02 09:50| 来源: 网络整理| 查看: 265

Python 模块虽多,但也不可能满足所有需求。而且,模块为了便于使用,通常都封装过度,有些功能无法灵活使用,必须直接调用Windows API 来实现。要完成这一目标,有两种办法,一种是使用 C 编写 Python 扩展模块,另一种就是编写普通的 DLL 通过 python 的 ctypes 来调用。

Python 没有自带访问 windows 系统 API 的库的,需要下载 pywin32,pywin32 是一个第三方模块库,主要的作用是方便 python 开发者快速调用 windows API 的一个模块库。它直接包装了几乎所有的 Windows API,可以方便地从 Python 直接调用,该模块另一大主要功能是通过 Python 进行 COM 编程。

Python extensions for Microsoft Windows Provides access to much of the Win32 API, the ability to create and use COM objects, and the Pythonwin environment. 翻译过来就是:pywin32 是 针对 Microsoft Windows 的 Python扩展,提供了对大部分 Win32 API 的访问、创建、和使用 COM对象 的能力以及 Pythonwin 环境。

pywin32 提供了齐全的windows 常量、接口、线程 以及 COM机制 等等。Windows Pywin32 允许你像 VC 一样的形式来使用PYTHON开发 win32 应用。代码风格可以类似 win32 sdk,也可以类似MFC,由你选择。如果你仍不放弃vc一样的代码过程在python下,那么这就是一个不错的选择。

1、window 消息、句柄

为了查找目标窗口的句柄,可以下载一个微软自家的 Spy++,可以很方便的查看窗体的消息。

深入理解 windows 消息机制:https://blog.csdn.net/liulianglin/article/details/14449577 Microsoft Win32 程序员参考 (在线 API):http://www.yfvb.com/help/win32sdk/index.htm

句柄:是一个 32 位整数,在 windows 中标记对象用,类似一个 dict 中的 key。在 win32 编程的世界里,包括 "窗口、文本框 等所有控件" 都是 窗体,所有的窗体都有独立的句柄。要操作任意一个窗体,你都需要找到这个窗体的句柄 。窗口句柄(具体位数跟个人PC操作系统位数相关),它表示的是消息所属的窗口。我们通常开发的程序都是窗口应用程序,一般一个消息都是和某个窗口相关联的。比如我们在某个活动窗口按下鼠标右键,此时产生的消息就是发送给该活动窗口的。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)。补充一下:“句柄”---在Windows程序中,有各种各样的资源,系统在创建这些资源的时候,都会为他们分配内存,并返回标识这些资源的标识号,这个标识号就是句柄)。消息:即 消息的标识符,是一些常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。在 Windows 中消息是由一个数值表示的,不同的消息对应不同的数值。 消息 是 windows 应用的重要部分,用来告诉窗体 "发生了什么",比如 给一个按钮发送BN_CLICKED 这么个消息,按钮就知道 "哦,我被点了",才能执行相应的下一步操作。但是当这些消息种类多到足以挑战我们的 IQ 时,所以聪明的程序开发者便想到将这些数值定义为WM_XXX 宏的形式。例如,鼠标左键按下的消息--WM_LBUTTONDOWN,键盘按下消息--WM_KEYDOWN,字符消息--WM_CHAR,等等。消息标识符以常量命名的方式指出消息的含义。当窗口过程接收到消息之后,他就会使用消息标识符来决定如何处理消息。例如、WM_PAINT告诉窗口过程窗体客户区被改变了需要重绘。符号常量指定系统消息属于的类别,其前缀指明了处理解释消息的窗体的类型。wParam 和 lParam:用于指定消息的附加信息。例如,当我们收到一个键盘按下消息的时候,message 成员变量的值就是 WM_KEYDOWN,但是用户到底按下的是哪一个按键,我们就得拜托这二位,由他们来告知我们具体的信息。 time 和 pt:这俩个变量分别被用来表示消息投递到消息队列中的时间和鼠标当前的位置,一般情况下不怎么使用(但不代表没用)

PyWin32 地址:https://github.com/mhammond/pywin32 PyWin32 文档:http://timgolden.me.uk/pywin32-docs/contents.html

2、安装 pywin32

安装:pip install pywin32

win32api :模块内定义了常用的一些 API函数,例如:MessageBoxwin32gui :模块内定义了一些有关 图形操作的API,例如:FindWindowwin32con :模块内定义了 windows API 内的宏,即 宏常量。例如 MessageBox 内的 MB_OK。( ps:con 个人理解 是 const 常量 的意思 )

安装完成后,在 Python 安装路径下 

Lib\site-packages\win32 下是所有的 API 支撑模块。Lib\site-packages\win32com 下是 COM 的支撑模块。

在 Lib\site-packages 下有一个 PyWin32.CHM 帮助文件,对 Windows 编程有一定基础的看了这个帮助文件就能很快上手。pywin32 把 Windows API 按照功能分了一些大类,每一个大类作为一个模块。以下是所有的模块:

mmapfile:提供对内存映射文件 API 的访问odbc:odb 数据库 apiperfmon:包装性能监视器功能的模块。pywintypes:支持常见 Windows 类型的模块。servicemanager:与 Windows 服务控制管理器交互的模块。timer:包装 Win32 Timer 函数的扩展win2kras:将 Windows 2000 扩展封装到远程访问服务 (RAS) API 的模块。win32api:提供了常用的用户APIwin32clipboard:提供了有关粘贴板的APIwin32con:有关的常量。提供了消息常量的操作API。win32console:控制台win32cred:凭证管理功能的接口。此模块中的功能仅适用于 Windows XP 及更高版本。win32crypt:win32 Cryptography API 的接口win32event:提供 win32 事件/等待API接口win32evtlog:封装了 Windows Win32 事件日志 API。win32file:提供了有关文件操作的APIwin32gui:提供了有关 windows 用户界面图形操作的APIwin32help:Win32 API 的帮助win32inet:Windows internet (wininet) API 接口win32job:win32 进程和线程 API 的接口,在 Windows 2000 及更高版本中可用。win32lz:封装 Windows LZ 压缩例程的模块win32net:Windows 网络API的模块win32pdh:封装 Windows 性能数据帮助 API 模块win32pipe:管道 apiwin32print:Windows 打印 API 的模块win32process:进程 apiwin32profile:包装用于处理用户配置文件的函数win32ras:封装 Windows Remote Access Service (RAS) APIwin32security:win32 安全 API 接口win32service:服务win32tracewin32transaction:内核事务管理器函数 模块,用于事务NTFS和事务注册表函数。win32ts:此模块中的所有函数都接受关键字参数win32wnet:公开 Windows Networking API 的模块。winxpgui:xp 图像用户界面 API

比如 文件类 API 就在模块 win32file 中,进程类 API 在模块 win32process 中。在使用的时候,按需导入相关模块就行了,win32con 则定义了所有的常量,几乎是必不可少的,一些难以分类的 API 则在模块 win32api 中(大部分是kernel32.dll导出的API)。

部分模块之间还存在一些交叉,比如 CreateFile 的参数中用到的 GENERIC_READ 常量,在 win32con 中有定义,在 win32file 中也有定义。用户只要大概知道这个是文件 API 用到的常量,那么不管你写 win32file.GENERIC_READ还是 win32con.GENERIC_READ 都是可以的。关闭句柄用的 CloseHandle 函数也是在两个模块中都有定义的。需要注意的是,微软提供的 Wsa 系列网络 API 也都在 win32file 模块中,因为很多操作系统都是把套接字也用为文件对象来操作的。

如果不清楚要使用的 API 在哪个模块中,到 帮助文件 里搜索一下就可以得到答案。

如果对 pywin32 中如何调用某个 API 不熟悉,那么查看 Pywin32.CHM 就足够了,如果对 API 本身的参数定义和使用不熟悉,那还得继续看 MSDN。

3、使用 pywin32 编写 windows 的 GUI

《python 宝典》:https://wenku.baidu.com/view/1f4eb95df011f18583d049649b6648d7c0c70830.html

示例:Helloworld:

示例:创建文件

在 Lib\site-packages\win32\Demos 目录下有很多例子,如果不清楚 pywin32 怎么用,可以看这些例子,比如 使用 API 进行文件操作:

# This is a "demo" of win32file - it used to be more a test case than a # demo, so has been moved to the test directory. # Please contribute your favourite simple little demo. import win32file, win32api, win32con import os # A very simple demo - note that this does no more than you can do with # builtin Python file objects, so for something as simple as this, you # generally *should* use builtin Python objects. Only use win32file etc # when you need win32 specific features not available in Python. def SimpleFileDemo(): testName = os.path.join(win32api.GetTempPath(), "win32file_demo_test_file") if os.path.exists(testName): os.unlink(testName) # Open the file for writing. 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() # Open it for reading. 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()

点击 鼠标

win32gui  和 win32ui :从字面意思来看,一个是 gui(图形用户接口),一个是 ui (用户接口),但是看不出有什么区别,查看源码也没发现有什么说明。

 示例:

import win32gui, win32api, win32con # 获取鼠标当前位置的坐标 win32api.GetCursorPos() # 将鼠标移动到坐标处 win32api.SetCursorPos((200, 200)) # 左点击 win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 200, 200, 0, 0) win32api.mouse_event(win32con.MUOSEEVENTF_LEFTUP, 200, 200, 0, 0) # 获取窗口句柄 win32gui.FindWindow(None, 'qq') win32gui.FindWindow('TXGuiFoundation', None) # 通过坐标获取窗口句柄 hw = win32api.WindowFromPoint(win32api.GetCursorPos()) # 获取窗口classname win32gui.GetClassName(hw) # 获取窗口标题 win32gui.GetWindowText(hw) # 获取窗口坐标 win32gui.GetwindowRect(hw)

通过窗口标题获取句柄 import win32gui hld = win32gui.FindWindow(None,u"Adobe Acrobat") #返回窗口标题为Adobe Acrobat的句柄

通过父窗口句柄获取子句柄 #parent为父窗口句柄id def get_child_windows(parent): ''' 获得parent的所有子窗口句柄 返回子窗口句柄列表 ''' if not parent: return hwndChildList = [] win32gui.EnumChildWindows(parent, lambda hwnd, param: param.append(hwnd), hwndChildList) return hwndChildList

根据句柄获取句柄标题和类名 import win32gui title = win32gui.GetWindowText(jbid) #jbid为句柄id #获取标题 clsname = win32gui.GetClassName(jbid) #获取类名

根据句柄获取窗口位置 import win32gui left, top, right, bottom = win32gui.GetWindowRect(jbid) #分别为左、上、右、下的窗口位置

根据句柄进行点击操作 import win32api,win32con win32api.SetCursorPos([横坐标, 纵坐标]) #根据横纵坐标定位光标 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) #给光标定位的位置进行右击操作

根据句柄将窗口放在最前 win32gui.SetForegroundWindow(jbid)

查找窗体句柄

在 win32 编程的世界里,包括 "窗口、文本框 等所有控件" 都是 窗体,所有的窗体都有独立的句柄。要操作任意一个窗体,你都需要找到这个窗体的句柄,这里,可以用到 FindWindow函数和FindWindowEx函数。在 pywin32 中,他们都属于 win32gui 的模块。

FindWindow(lpClassName=None, lpWindowName=None):

描述:自顶层窗口(也就是桌面)开始搜索条件匹配的窗体,并返回这个窗体的句柄。不搜索子窗口、不区分大小写。找不到就返回0  参数:  lpClassName:字符型,是窗体的类名,这个可以在Spy++里找到。  lpWindowName:字符型,是窗口名,也就是标题栏上你能看见的那个标题。  说明:这个函数我们仅能用来找主窗口。

示例代码 1 (获取所有窗口句柄。使用 win32gui 模块) :

import win32gui titles = set() def foo(hwnd, mouse): # 去掉下面这句就所有都输出了,但是我不需要那么多 if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd): titles.add(win32gui.GetWindowText(hwnd)) def test(): win32gui.EnumWindows(foo, 0) lt = [t for t in titles if t] lt.sort() for t in lt: print(t) if __name__ == '__main__': test() 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(): if t is not "": print(h, t)

示例代码 2 :( 使用 win32ui 模块)

import win32ui def test(): dlg = win32ui.CreateFileDialog(1) # 1表示打开文件对话框 dlg.SetOFNInitialDir('E:/Python') # 设置打开文件对话框中的初始显示目录 dlg.DoModal() filename = dlg.GetPathName() # 获取选择的文件名称 print(filename) if __name__ == '__main__': test()

示例代码 3:

import win32api import win32con import win32gui import win32ui import win32console import win32process import os import signal MAIN_HWND = 0 def is_win_ok(hwnd, starttext): s = win32gui.GetWindowText(hwnd) if starttext in s: print(s) global MAIN_HWND MAIN_HWND = hwnd return None return 1 def find_main_window(starttxt): global MAIN_HWND win32gui.EnumChildWindows(0, is_win_ok, starttxt) return MAIN_HWND def winfun(hwnd, lparam): s = win32gui.GetWindowText(hwnd) if len(s) > 3: print("winfun, child_hwnd: %d txt: %s" % (hwnd, s)) return 1 if __name__ == '__main__': os.system('start cmd') window_title = 'C:\Windows\system32\cmd.exe' window_handle = win32gui.FindWindow(None, window_title) window_handle_title = win32gui.GetWindowText(window_handle) window_handle_class_name = win32gui.GetClassName(window_handle) print(window_handle_title) print(window_handle_class_name) win32gui.CloseWindow(window_handle) # 窗口最小化 win32gui.SendMessage(window_handle, win32con.WM_CLOSE) # 关闭窗口 # win32api.SetCursorPos([0, 0]) # 设置 鼠标 位置 file_path = './test.txt' with open(file_path, 'w+') as f: pass os.system('start {0}'.format(file_path)) main_app = 'test.txt - 记事本' hwnd = win32gui.FindWindow(None, main_app) win32gui.CloseWindow(hwnd) # 窗口最小化 print(win32gui.GetWindowText(hwnd)) print(type(hwnd)) print(hwnd) if hwnd < 1: hwnd = find_main_window(main_app) print(type(hwnd)) print(hwnd) if hwnd: win32gui.EnumChildWindows(hwnd, winfun, None) thread, processId = win32process.GetWindowThreadProcessId(hwnd) print(thread) # print(processId, signal.CTRL_BREAK_EVENT) # os.kill(processId, signal.CTRL_C_EVENT) # os.kill(processId, signal.CTRL_BREAK_EVENT) # Shows or hides a window and changes its state win32gui.ShowWindow(hwnd, 0) # win32gui.HideCaret(hwnd)

示例代码 4:

import win32gui import win32con import win32api import win32process import os spider_config_count = dict( mao_yan_spider=10, tao_piao_piao_spider=10, ) # 保存 句柄 和 句柄 title。 示例 { 100 : 'C:\Windows\system32\cmd.exe'} handle_title_dict = dict() # 通过 spider_config_count 生成 keyword_list。 keyword_list = list() # 每个 spider 对应的数量 spider_count_dict = dict() # 所有 进程 对应的数量 process_count_dict = dict() for temp_k, temp_v in spider_config_count.items(): keyword_list.append(temp_k) def get_windows_handle(hwnd, mouse): if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd): handle_title_dict.update({hwnd: win32gui.GetWindowText(hwnd)}) def get_all_windows_handle(): win32gui.EnumWindows(get_windows_handle, 0) for k, v in handle_title_dict.items(): # print('{0} : {1}'.format(k, v)) pass def close_process(): # for k, v in WINDOWS_HANDLE_DICT.items(): # # print('{0} : {1}'.format(k, v)) # if WINDOWS_HANDLE_DICT[k] in WINDOWS_HANDLE_TITLE_LIST: # print('{0} : {1}'.format(k, v)) pass def display_all_spider_count(): for k, v in handle_title_dict.items(): if handle_title_dict[k]: for keyword in keyword_list: if keyword in v: if not spider_count_dict.get(keyword): spider_count_dict[keyword] = 1 else: spider_count_dict[keyword] += 1 for k, v in spider_count_dict.items(): print('{0} : {1}'.format(k, v)) def display_all_process_count(): for k, v in handle_title_dict.items(): if handle_title_dict[k]: if not process_count_dict.get(v): process_count_dict[v] = 1 else: process_count_dict[v] += 1 for k, v in process_count_dict.items(): print('{0} : {1}'.format(k, v)) pass def monitoring_spider_count(): pan = 'E:' # spider_path = 'PythonSpider/maoyan' spider_path = 'PythonSpider/taopiaopiaoSpider' for k, v in spider_config_count.items(): # for k_2, v_2 in spider_count_dict: if spider_count_dict.get(k): if spider_count_dict[k] < v: count = v - spider_count_dict[k] # win_cmd = 'for /L %i in (1,1,5) do start cmd /k "e: && cd PythonSpider" ' win_cmd = 'for /L %i in (1,1,{0}) do start cmd /k "{1} && cd {2} && scrapy crawl {3}"'.format( count, pan, spider_path, k ) os.system(win_cmd) else: count = v win_cmd = 'for /L %i in (1,1,{0}) do start cmd /k "{1} && cd {2} && scrapy crawl {3}"'.format( count, pan, spider_path, k ) os.system(win_cmd) pass def test(): get_all_windows_handle() for k, v in handle_title_dict.items(): # print('{0} : {1}'.format(k, v)) if handle_title_dict[k] == '无标题 - 记事本': print('{0} : {1}'.format(k, v)) # 如果记事本有 内容未保存,win32gui.SendMessage(k, win32con.WM_CLOSE) 这个无法关闭 # win32gui.SendMessage(k, win32con.WM_CLOSE) # 终止进程 方式 可以关闭记事本中有内容未保存 thread_id, process_id = win32process.GetWindowThreadProcessId(k) p_handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, process_id) win32api.TerminateProcess(p_handle, process_id) win32api.CloseHandle(p_handle) get_all_windows_handle() def test_2(): win_cmd = 'for /L %i in (1,1,5) do start cmd /k "e: && cd PythonSpider" ' os.system(win_cmd) if __name__ == '__main__': # display_all_spider_count() display_all_process_count() # monitoring_spider_count() pass

窗口句柄 发送消息 常用方法 键盘输入

python win32api win32gui win32con

推荐微软的 Spy++ (下载地址:https://download.csdn.net/download/freeking101/11002997)来查看窗口类名等信息。

# -*- coding:utf-8 -*- import time import win32gui import win32con import win32api # 从顶层窗口向下搜索主窗口,无法搜索子窗口 # FindWindow(lpClassName=None, lpWindowName=None) 窗口类名 窗口标题名 handle = win32gui.FindWindow("Notepad", None) # 获取窗口位置 left, top, right, bottom = win32gui.GetWindowRect(handle) # 获取某个句柄的类名和标题 title = win32gui.GetWindowText(handle) cls_name = win32gui.GetClassName(handle) # 打印句柄 print(handle) print(cls_name) # 搜索子窗口 # 枚举子窗口 hwndChildList = [] win32gui.EnumChildWindows(handle, lambda hwnd, param: param.append(hwnd), hwndChildList) # 父窗口句柄 若不为0,则按照z-index的顺序从hwndChildAfter向后开始搜索子窗体,否则从第一个子窗体开始搜索。 子窗口类名 子窗口标题 # FindWindowEx(hwndParent=0, hwndChildAfter=0, lpszClass=None, lpszWindow=None) subHandle = win32gui.FindWindowEx(handle, 0, "EDIT", None) # 获得窗口的菜单句柄 menuHandle = win32gui.GetMenu(subHandle) # 获得子菜单或下拉菜单句柄 # 参数:菜单句柄 子菜单索引号 subMenuHandle = win32gui.GetSubMenu(menuHandle, 0) # 获得菜单项中的的标志符,注意,分隔符是被编入索引的 # 参数:子菜单句柄 项目索引号 menuItemHandle = win32gui.GetMenuItemID(subMenuHandle, 0) # 发送消息,加入消息队列,无返回 # 参数:句柄 消息类型 WParam IParam win32gui.postMessage(subHandle, win32con.WM_COMMAND, menuItemHandle, 0) # wParam的定义是32位整型,high word就是他的31至16位,low word是它的15至0位。 # 当参数超过两个,wParam和lParam不够用时,可以将wParam就给拆成两个int16来使用。 # 这种时候在python里记得用把HIWORD的常数向左移16位,再加LOWORD,即wParam = HIWORD


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有