微信桌面端自动化(Windows)
在 Windows 上通过 computer_use + PowerShell 驱动微信(Weixin 4.x)等自绘 UI 应用:搜索会话、输入文字、发送消息。
核心要点(血泪教训)
- 微信 4.0 是自绘 UI:UIA 树为空(capture 返回 0 elements),无法读取界面内容,也无法用元素索引点击。只能靠键盘快捷键 + 坐标。
- PostMessage 键盘注入对微信无效:background 模式的 type/key 发不进微信输入框。
- Windows foreground lock:SetForegroundWindow 从非 UIAccess 进程调用会被拒绝。必须先模拟按一下 Alt 键解锁,再 SetForegroundWindow。
- SendInput 逐字符输入长中文会被 IME 干扰:文字乱码、符号重复、内容不完整。短文本(≤4字)可以 SendInput,长文本必须用剪贴板粘贴。
- 不要 Start-Process 启动微信新实例:会弹出"扫码登录"窗口而不是恢复已有窗口。微信已在运行时就复用现有进程。
标准流程
1. 确认微信运行状态
computer_use(action="list_apps") # 找 Weixin.exe / 微信,记下 PID
computer_use(action="list_windows") # 找标题为"微信"的主窗口(注意可能有两个微信窗口:
# 主窗口标题"微信"是大窗口,标题"Weixin"的小窗是浮窗,避开它)
若微信未运行:Start-Process 'C:\Program Files\Tencent\Weixin\Weixin.exe' 并等待。
2. 激活微信窗口到前台(关键步骤)
用 PowerShell + user32(模拟 Alt 解锁 foreground lock):
Add-Type @'
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")] public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
}
'@
$p = Get-Process Weixin | Where-Object { $_.MainWindowHandle -ne 0 } | Select-Object -First 1
[Win32]::keybd_event(0x12, 0, 0, [UIntPtr]::Zero) # Alt down
[Win32]::keybd_event(0x12, 0, 2, [UIntPtr]::Zero) # Alt up
Start-Sleep -Milliseconds 200
[Win32]::SetForegroundWindow($p.MainWindowHandle) # 返回 True 表示成功
(git-bash 中执行时注意转义 $ 为 \$," 为 \")
2b. 【推荐】SendKeys 一体化脚本(一次搞定搜索+发送)
cua-driver 的 foreground 模式会被 Windows foreground lock 反复拒绝(每次调用间用户一切窗口就失效)。 最可靠方案:在同一个 PowerShell 进程内完成"激活窗口 → 全部按键",中文一律走剪贴板:
$ErrorActionPreference = 'Stop'
Add-Type -AssemblyName System.Windows.Forms
Add-Type @'
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")] public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
}
'@
$p = Get-Process Weixin | Where-Object { $_.MainWindowHandle -ne 0 } | Select-Object -First 1
[Win32]::keybd_event(0x12, 0, 0, [UIntPtr]::Zero)
[Win32]::keybd_event(0x12, 0, 2, [UIntPtr]::Zero)
Start-Sleep -Milliseconds 200
$ok = [Win32]::SetForegroundWindow($p.MainWindowHandle)
Start-Sleep -Milliseconds 300
if (-not $ok) { Write-Host 'ACTIVATE_FAILED'; exit 1 }
# 搜索会话:Ctrl+F → 全选清空 → 粘贴名称 → 回车进入
[System.Windows.Forms.SendKeys]::SendWait('^f'); Start-Sleep -Milliseconds 500
[System.Windows.Forms.SendKeys]::SendWait('^a'); Start-Sleep -Milliseconds 200
[System.Windows.Forms.SendKeys]::SendWait('{DELETE}'); Start-Sleep -Milliseconds 200
Set-Clipboard -Value '会话名'
[System.Windows.Forms.SendKeys]::SendWait('^v'); Start-Sleep -Milliseconds 500
[System.Windows.Forms.SendKeys]::SendWait('{ENTER}'); Start-Sleep -Milliseconds 800
# 发送消息:粘贴内容 → 回车
Set-Clipboard -Value '消息内容'
[System.Windows.Forms.SendKeys]::SendWait('^v'); Start-Sleep -Milliseconds 300
[System.Windows.Forms.SendKeys]::SendWait('{ENTER}')
Write-Host 'DONE'
要点:SendKeys 只发 ASCII 快捷键(^f ^a ^v {ENTER} {DELETE}),中文全部 Set-Clipboard + 粘贴。 一次调用内完成可避免 foreground lock 反复发作。缺点是无法中途确认,只能靠最终用户确认。
3. 搜索并进入会话
computer_use(action="key", keys="ctrl+f", delivery_mode="foreground") # 微信搜索快捷键
computer_use(action="type", text="<会话名>", delivery_mode="foreground") # 短名称可 SendInput;名称长/含符号用剪贴板
computer_use(action="key", keys="return", delivery_mode="foreground") # 进入第一个搜索结果
4. 输入消息内容(长文本必须剪贴板粘贴)
Set-Clipboard -Value '<完整消息文本>' # 中文文本 UTF-16,无编码问题
然后:
computer_use(action="key", keys="ctrl+v", delivery_mode="foreground") # 粘贴
computer_use(action="key", keys="return", delivery_mode="foreground") # 回车发送
5. 验证
由于无法读取界面,必须让用户确认发送结果(用 clarify 提问)。
陷阱清单
- 窗口识别:
focus_app可能定位到小浮窗(标题 "Weixin",约 258x83)而不是主窗口(标题"微信",~880x639)。用list_windows核对 PID 和标题,capture 时显式传pid+window_id。 No active window错误:foreground 操作前先capture(pid=..., window_id=...)建立窗口上下文。- 中文标点:
「」~等符号在注入时容易显示异常,写消息内容时优先用基础中文标点(,。!)。 - 发送后文字残留:若上一条消息没发出去,输入框会有残留,再次输入前先按
ctrl+a+delete清空(或让用户手动清)。 - 误发多条:发错格式的消息会留在群里,提醒用户手动撤回。
- 辅助视觉模型不可用:
vision_analysis可能报unknown variant image_url(辅助模型不支持图片),此时无法靠截图确认界面,只能靠键盘流程 + 用户确认。
验证步骤
完成后向用户确认:
- 会话是否进入正确(群名/联系人名)
- 消息内容是否完整无乱码
- 是否发送成功