Python `win32` API:Windows 系统级编程的强大接口

Python win32 API:Windows 系统级编程的强大接口 (讲座模式)

大家好!欢迎来到今天的“Python 玩转 Windows”讲座。今天咱们要聊的是一个听起来有点吓人,但用起来绝对让你感觉自己像个黑客(假的!)的工具:Python win32 API。

开场白:为什么我们要搞事情?

你可能要问了:“Python 不是写网页、搞数据分析的吗?为啥要碰 Windows API 这种底层的东西?” 问得好!原因很简单:

  1. 能力更强:Python 默认的功能很强大,但有些 Windows 特有的操作,比如控制窗口、读写注册表、甚至操作硬件,需要直接调用 Windows API 才能搞定。
  2. 效率更高:有些性能敏感的任务,用 Python 脚本调用 C/C++ 写的 API,比纯 Python 代码效率高得多。
  3. 满足好奇心:想知道 Windows 内部是怎么运作的?win32 API 是你的敲门砖。当然,也可能是你的潘多拉魔盒(滑稽.jpg)。

win32 API 是什么?

你可以把 win32 API 想象成 Windows 操作系统提供给程序员的一套“积木”。这些“积木”都是用 C/C++ 写的函数,可以用来执行各种 Windows 系统操作。

Python win32 模块是什么?

Python win32 模块(更准确地说是 pywin32 扩展)就是把这些 C/C++ 的“积木”封装起来,让你可以用 Python 代码来调用它们。简单来说,它是一个翻译器,让你能用 Python 的方式跟 Windows 系统“对话”。

安装 pywin32

首先,确保你安装了 pywin32 扩展。没装?赶紧装!打开你的命令行工具,输入:

pip install pywin32

安装完成后,运行以下命令来注册 pywin32

python Scripts/pywin32_postinstall.py -install

开始玩“积木”:第一个小例子

我们先来个最简单的例子:弹出一个消息框。

import win32gui
import win32con

win32gui.MessageBox(0, "Hello, Windows from Python!", "Greeting", win32con.MB_OK)

运行这段代码,你会看到一个熟悉的 Windows 消息框跳出来,上面写着 "Hello, Windows from Python!"。是不是很简单?

  • win32gui:这个模块包含了跟 GUI(图形用户界面)相关的函数。
  • win32con:这个模块包含了各种 Windows 常量,比如 MB_OK,表示消息框上只有一个“确定”按钮。
  • win32gui.MessageBox():这就是我们调用的 Windows API 函数,用来显示消息框。

进阶:查找窗口并发送消息

接下来,我们来个稍微复杂一点的:查找一个窗口,并向它发送消息。比如,我们想找到记事本窗口,并让它显示 "Hello from Python!"。

import win32gui
import win32con

# 窗口标题
window_title = "无标题 - 记事本"

# 查找窗口句柄
hwnd = win32gui.FindWindow(None, window_title)

# 检查是否找到窗口
if hwnd == 0:
    print("找不到窗口:", window_title)
else:
    # 发送消息
    win32gui.SendMessage(hwnd, win32con.WM_SETTEXT, None, "Hello from Python!")

这段代码做了什么?

  1. win32gui.FindWindow(None, window_title):根据窗口标题查找窗口句柄(hwnd)。窗口句柄是 Windows 用来标识窗口的唯一 ID。
  2. win32gui.SendMessage(hwnd, win32con.WM_SETTEXT, None, "Hello from Python!"):向窗口发送 WM_SETTEXT 消息,告诉它修改窗口的文本内容。

重要提示:运行这段代码前,确保你打开了一个标题为 "无标题 – 记事本" 的记事本窗口。

深入虎穴:一些常用的 win32 模块

pywin32 模块非常庞大,包含了各种各样的子模块。下面列出一些常用的模块,以及它们的功能:

模块名 功能
win32gui 操作 GUI 窗口、控件等
win32con Windows 常量定义,如消息代码、窗口样式等
win32api 访问底层 Windows API 函数
win32com 操作 COM 组件(如 Excel、Word 等)
win32service 管理 Windows 服务
win32event 处理事件、信号量等同步对象
win32file 文件操作,包括底层的文件 I/O
win32process 进程管理,如创建、终止进程等
win32net 网络操作,如访问网络资源等
win32security 安全相关操作,如用户权限管理等
win32ts 远程桌面服务相关操作。
win32pdh 性能计数器相关操作
win32print 打印机相关操作
win32clipboard 剪贴板相关操作
win32console 控制台相关操作
win32pipe 管道通信相关操作
win32inet Internet相关操作
win32ras 远程访问服务相关操作
win32profile 用户配置文件相关操作
win32wnet Windows网络相关操作
win32transaction 事务处理相关操作

实战演练:模拟鼠标点击

现在,我们来个更酷的:模拟鼠标点击。这个功能在自动化测试、游戏辅助等方面很有用。

import win32api
import win32con
import time

# 鼠标点击坐标 (屏幕坐标)
x = 100
y = 200

# 模拟鼠标左键点击
win32api.SetCursorPos((x, y))  # 移动鼠标到指定位置
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0)  # 按下左键
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0)    # 释放左键

time.sleep(1)

# 模拟鼠标右键点击
win32api.SetCursorPos((x, y))  # 移动鼠标到指定位置
win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN, x, y, 0, 0)  # 按下右键
win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP, x, y, 0, 0)    # 释放右键

这段代码做了什么?

  1. win32api.SetCursorPos((x, y)):把鼠标光标移动到屏幕坐标 (x, y) 的位置。
  2. win32api.mouse_event():模拟鼠标事件。
    • MOUSEEVENTF_LEFTDOWN:按下鼠标左键。
    • MOUSEEVENTF_LEFTUP:释放鼠标左键。
    • MOUSEEVENTF_RIGHTDOWN:按下鼠标右键。
    • MOUSEEVENTF_RIGHTUP:释放鼠标右键。

注意:运行这段代码时,鼠标会突然移动到指定位置并点击,可能会影响你正在进行的操作。

再进一步:读取注册表

注册表是 Windows 存储系统配置信息的地方。我们可以用 win32api 读取注册表信息。

import win32api
import win32con

# 注册表路径
key_path = "SOFTWARE\Microsoft\Windows\CurrentVersion"

# 要读取的键名
value_name = "ProgramFilesDir"

try:
    # 打开注册表键
    key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, key_path, 0, win32con.KEY_READ)

    # 读取键值
    value, value_type = win32api.RegQueryValueEx(key, value_name)

    # 关闭注册表键
    win32api.RegCloseKey(key)

    print(f"{value_name}: {value}")

except Exception as e:
    print("Error:", e)

这段代码做了什么?

  1. win32api.RegOpenKey():打开指定的注册表键。
    • HKEY_LOCAL_MACHINE:表示本地计算机的注册表根键。
    • key_path:表示要打开的键的路径。
    • 0:保留参数,通常为 0。
    • KEY_READ:表示以只读方式打开键。
  2. win32api.RegQueryValueEx():读取键的值。
    • key:要读取值的键。
    • value_name:要读取的键名。
  3. win32api.RegCloseKey():关闭注册表键。

这段代码会读取 HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersion 下的 ProgramFilesDir 键的值,也就是程序安装目录。

COM 组件:操作 Office (Excel)

win32com 模块可以让你用 Python 操作 COM 组件,比如 Excel、Word 等。这里我们演示如何用 Python 创建一个 Excel 文件,并写入一些数据。

import win32com.client

# 创建 Excel 应用对象
excel = win32com.client.Dispatch("Excel.Application")

# 创建一个新的工作簿
workbook = excel.Workbooks.Add()

# 获取第一个工作表
sheet = workbook.Sheets(1)

# 写入数据
sheet.Cells(1, 1).Value = "Hello"
sheet.Cells(1, 2).Value = "from"
sheet.Cells(1, 3).Value = "Python!"

# 保存工作簿
workbook.SaveAs("hello.xlsx")

# 关闭工作簿
workbook.Close()

# 退出 Excel 应用
excel.Quit()

这段代码做了什么?

  1. win32com.client.Dispatch("Excel.Application"):创建 Excel 应用对象。
  2. excel.Workbooks.Add():创建一个新的工作簿。
  3. workbook.Sheets(1):获取第一个工作表。
  4. sheet.Cells(1, 1).Value = "Hello":在单元格 (1, 1) 写入 "Hello"。
  5. workbook.SaveAs("hello.xlsx"):保存工作簿为 "hello.xlsx"。
  6. workbook.Close():关闭工作簿。
  7. excel.Quit():退出 Excel 应用。

运行这段代码后,你会看到一个名为 "hello.xlsx" 的 Excel 文件被创建,并且写入了 "Hello from Python!"。

错误处理:小心驶得万年船

调用 Windows API 很容易出错,所以一定要做好错误处理。pywin32 模块通常会抛出 pywintypes.error 异常。

import win32gui
import win32con
import pywintypes

try:
    hwnd = win32gui.FindWindow(None, "不存在的窗口")
    if hwnd == 0:
        raise Exception("Window not found")
    win32gui.SendMessage(hwnd, win32con.WM_SETTEXT, None, "Hello")
except pywintypes.error as e:
    print("Windows API Error:", e)
except Exception as e:
    print("Python Error:", e)

一些小技巧

  • 查文档pywin32 模块的文档比较 sparse,但 Windows API 的文档非常详细。你可以参考 Microsoft 的官方文档。
  • 多尝试win32 API 的参数类型很严格,一定要仔细阅读文档,了解每个参数的含义和类型。
  • 善用 Google:遇到问题,先 Google 一下,很可能已经有人遇到过同样的问题,并且找到了解决方案。
  • 注意权限:有些 Windows API 需要管理员权限才能调用。
  • 小心使用win32 API 功能强大,但也容易破坏系统。一定要小心使用,避免造成不必要的损失。

代码示例:枚举所有顶层窗口

import win32gui

def enum_windows_callback(hwnd, param):
    title = win32gui.GetWindowText(hwnd)
    if title:
        print(f"HWND: {hwnd}, Title: {title}")

win32gui.EnumWindows(enum_windows_callback, None)

代码示例:获取屏幕分辨率

import win32api

width = win32api.GetSystemMetrics(0)  # SM_CXSCREEN
height = win32api.GetSystemMetrics(1) # SM_CYSCREEN

print(f"Screen width: {width}")
print(f"Screen height: {height}")

代码示例:发送按键消息

import win32api
import win32con
import time

# 找到目标窗口 (例如,记事本)
hwnd = win32gui.FindWindow(None, "无标题 - 记事本")

if hwnd:
    # 激活窗口
    win32gui.SetForegroundWindow(hwnd)
    time.sleep(0.5) # 等待窗口激活

    # 发送 'A' 键 (虚拟键码 0x41)
    win32api.PostMessage(hwnd, win32con.WM_KEYDOWN, 0x41, 0)
    win32api.PostMessage(hwnd, win32con.WM_KEYUP, 0x41, 0)
else:
    print("未找到窗口")

总结

Python win32 API 是一个强大的工具,可以让你用 Python 代码与 Windows 系统进行深度交互。虽然学习曲线比较陡峭,但只要掌握了基本原理和常用模块,就能开发出各种有趣实用的程序。希望今天的讲座能帮助你入门 win32 API,开启你的 Windows 系统编程之旅!记得,小心驶得万年船!

Q&A

现在,大家有什么问题吗?欢迎提问!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注