Windows 微信自动发送工具。支持搜索微信联系人并发送文字、图片、文件。通过 GUI 自动化控制微信窗口,无需微信开放接口。
触发场景: 离开电脑时,远程指令OpenClaw发送图片/文件给微信联系人。条件: 微信打开并登录(允许最小化)。举例:1、把桌面上的龙虾图片发送给张三(默认微信发送);2、查找D盘最新的报价单Excel表并发送给李四(默认微信发送)。
找窗口 → 恢复最小化 → 激活 → 搜索联系人 → 进入聊天 → 发送内容
用户说「发 xxx 文件给 “张三”」时,必须先搜索确认,再发送:
1. 调用 find_file.py --name 关键词 --dirs 搜索目录 搜索文件
2. 根据结果数量选择策略:
├─ 0 个 → 告知未找到,请提供完整路径或换关键词
├─ 1 个 → 告知文件信息,询问「确认发送?」
├─ 2~15 个 → 单行列表,让用户选择序号
└─ >15 个 → 按目录分组摘要,让用户缩小范围
3. 用户确认后,调用 send_file.py 发送
4. 反馈发送结果
搜索参数说明:
--name:关键词(模糊匹配,不区分大小写)--dirs:搜索目录,逗号分隔(默认桌面/下载/文档/Workspace)--depth:递归深度,默认3--ext:限定扩展名(如 xlsx、pdf)--limit:最多返回条数,默认50python scripts/send_message.py --contact "联系人名字" --message "消息内容"
python scripts/send_image.py --contact "联系人名字" --image "图片路径"
python scripts/send_file.py --contact "联系人名字" --file "文件路径"
推荐使用 batch_send.py,一个脚本搞定搜索→确认→发送全流程:
# 搜索并交互式发送(脚本会展示文件列表,等待用户回复序号)
python scripts/batch_send.py --keyword "报价单" --contact "张三"
# 指定目录和深度
python scripts/batch_send.py --keyword "报价单" --dirs "D:/" --depth 4 --contact "张三"
# 限定扩展名
python scripts/batch_send.py --keyword "报价单" --ext xlsx --contact "张三"
# 直接发送指定序号(跳过交互确认,用于 agent 自动化)
python scripts/batch_send.py --keyword "报价单" --contact "张三" --indices "1,3"
# 干跑测试(只展示文件,不实际发送)
python scripts/batch_send.py --keyword "报价单" --contact "张三" --dry-run
交互流程示例:
$ python scripts/batch_send.py --keyword "报价单" --contact "张三"
找到 32 个匹配文件,已按项目分类:
📁 目录1
• [1] 报价单1.xlsx
• [2] 报价单2.xlsx
• [3] 报价单3.xlsx
• [4] 报价单4.xlsx
📁 目录2
• [5] 报价单5.xlsx
...
• [32] 报价单6.pdf
回复序号选择发送(多个序号用逗号分隔,如 1,3,5)
请回复序号:3
发送 [3] 报价单3.xlsx → 张三 ...
✅ 发送成功
# 搜索名字包含"日报"的文件
python scripts/find_file.py --name "日报"
# 指定目录和扩展名
python scripts/find_file.py --name "报价单" --dirs "C:/Users/admin/Desktop" --ext xlsx
# 输出 JSON(供程序解析)
python scripts/find_file.py --name "日报" --json
from scripts.wechat_sender import WeChatSender
# 初始化
sender = WeChatSender()
# 发送文字
sender.send_message("张三", "你好,这是测试消息")
# 发送图片
sender.send_image("张三", r"C:\path\to\image.jpg")
# 发送文件
sender.send_file("张三", r"C:\path\to\file.xlsx")
| 脚本 | 功能 | 参数 |
|---|---|---|
| --- | --- | --- |
find_file.py | 搜索文件,返回匹配列表 | --name, --dirs, --ext, --limit, --json |
batch_send.py | 集成搜索+确认+发送(推荐) | --keyword, --contact, --dirs, --ext, --depth, --indices, --dry-run |
send_message.py | 发送文字消息 | --contact, --message |
send_image.py | 发送图片 | --contact, --image |
send_file.py | 发送文件 | --contact, --file |
wechat_sender.py | 核心类库 | - |
GetWindowRect 返回负坐标(-32000),如果先按坐标筛选会误排除真正的微信主窗口,选到隐藏的辅助窗口(症状:只弹表情包按钮)。正确流程:先对所有候选窗口 IsIconic + ShowWindow(9) 恢复,等坐标变为正后再筛选面积最大的可见窗口。用 ShowWindow(hwnd, 9) (SW_RESTORE),不能用 ShowWindow(hwnd, 5) (SW_SHOW)Chrome_WidgetWin 找到并关闭公众号弹窗等子窗口sys.stdout.reconfigure(encoding='utf-8')SetForegroundWindow 或 SetWindowPos(HWND_TOPMOST) 均不可靠。Windows 只允许前台进程的线程切换前台窗口,必须用以下组合:```python
foreground_thread = user32.GetWindowThreadProcessId(user32.GetForegroundWindow(), None)
wechat_thread = user32.GetWindowThreadProcessId(hwnd, None)
user32.AttachThreadInput(foreground_thread, wechat_thread, True) # 附加线程
user32.keybd_event(0x12, 0, 0, 0) # 模拟 Alt 键(欺骗 Windows)
user32.keybd_event(0x12, 0, 2, 0)
user32.SetForegroundWindow(hwnd)
user32.AttachThreadInput(foreground_thread, wechat_thread, False) # 取消附加
```
pip install "pyautogui>=0.63.0,<1.0.0" "pyperclip>=1.8.0,<2.0.0" "pywin32>=306,<310" "Pillow>=10.0.0,<13.0.0"pip install "pyautogui>=0.63.0,<1.0.0" "pyperclip>=1.8.0,<2.0.0" "pywin32>=306,<310" "Pillow>=10.0.0,<13.0.0"
⚠️ 重要:
find_wechat_window() 在窗口恢复前按坐标筛选,最小化窗口坐标为负(-32000)被排除,选到隐藏辅助窗口,导致激活时只触发表情包按钮IsIconic + ShowWindow(9) 恢复,再按正坐标筛选面积最大的可见窗口search_contact() 中 Ctrl+F 后点击搜索框在 cron 环境下可能失败(点击打偏),导致联系人名字输入到错误位置、消息发给错误的人typewrite(contact_name) 输入即可activate_window 验证失败时返回 False,让调用者感知失败activate_window 方法改用 AttachThreadInput + keybd_event(Alt) + SetForegroundWindow 组合,确保微信窗口必定切换到前台共 12 个版本