本篇就来兑现在《PowerShell UI自动化测试框架》中的承诺:自动给QQ群发消息。
知识点
- 假定QQ正在运行,并且已经登录。如若自动给QQ群发送消息,须要三步:第一步,点击QQ群,弹出聊天窗口;第二步,在消息框输入消息;第三步,点击“发送”按钮。
- 在“UI Automation PowerShell扩展”找出一个窗口,然后再找其中的一个按钮,默认是支持递归遍历的。但是如果窗口中控件错综,要找的目标按钮节点较深,递归起来效率非常低。所以我简单的写了个小函数 Get-UiaControlByChildrenIndex,能根据控件的索引路径来查找,避免走弯路。
- 第三个是一个坎,之前和Victor讨论过,QQ的发送消息的发送框,不是一个标准的windows文本框,如果是,直接可以用Set-UiaEditText赋值。但是可惜了,它不是。我给出的解决方法是:鼠标右击,弹出上下文菜单,然后将内容粘贴过去。
- 最后就是发挥PowerShell自定义对象的魅力了:自定义属性,自定义方法。
因为我不在腾讯上班,所以没必要把所有东西都写完。只是为朋友们做个演示。
脚本
<#
# 操作系统 :Windows 8.1(中文简体)
# PowerShell:4.0
# QQ版本 :qq5.2 10446
#>
Import-Module E:\Powershell\UIA\UIAutomation.dll
# QQ 上下文
$QQContext = [PSCustomObject]@{
MainWindow = $null # 主界面
Process = $null # 进程
TaskBar = $null #任务栏图标
}
#############################
##通过粘切按钮设置QQ中编辑框文本
#############################
Function Set-QQEditTextByCopy
{
param
(
[Parameter(ValueFromPipeline=$true)]
[UIAutomation.UiElement]$EditControl,
[string]$Text
)
$Text | clip.exe
#弹出上下文菜单
$EditControl.InvokeContextMenu()
#粘切按钮
$pasterMenu = (Get-UiaWindow -Class 'TXGuiFoundation' -Name 'TXMenuWindow' | Get-UiaControlChildren)[2]
$pasterMenu| Invoke-UiaControlClick -DoubleClick | Out-Null
}
######################
##根据索引联获取子窗口
######################
function Get-UiaControlByChildrenIndex
{
param(
[Parameter(ValueFromPipeline=$true)]
#父控件
$Parent,
#索引联数组,比如@(1,3,2),逻辑类似 Children[1].Children[3].Children[2]
[int[]]$IndexChain
)
$result=$Parent
$IndexChain | foreach {
$result = ($result | Get-UiaControlChildren)[$_]
}
return $result
}
######################
##初始化QQ主窗口
######################
function Get-QQ
{
$QQContext.MainWindow
#主窗口
$qqWindow = Get-UiaWindow -Name 'QQ' -Class 'TXGuiFoundation' -ProcessId $QQContext.Process.Id
$searchControl = Get-UiaControlByChildrenIndex -Parent $qqWindow -IndexChain @(4,1,1) | Get-UiaControlChildren
$HubMenus = Get-UiaControlByChildrenIndex -Parent $qqWindow -IndexChain @(4,1,3,0,0,0,0) | Get-UiaTab | Get-UiaTabItem
$QQContext.MainWindow = [PSCustomObject]@{
#窗口缓存
Window = $qqWindow
#关闭按钮
CloseButton = Get-UiaControlByChildrenIndex -Parent $qqWindow -IndexChain @(5,0)
#最小化按钮
MinimizeButton = Get-UiaControlByChildrenIndex -Parent $qqWindow -IndexChain @(5,1)
#群与联系人切换按钮
HubMenus = [PSCustomObject]@{
#好友按钮
Friends = $HubMenus[0]
#群组按钮
Group = $HubMenus[1]
#会话按钮
Conversation = $HubMenus[2]
#QQ空间
QZone=$HubMenus[3]
#腾讯微博
Weibo=$HubMenus[4]
}
#搜索
Search = [PSCustomObject]@{
Box = $searchControl[1]
Button = $searchControl[0]
}
}
#搜索方法
$QQContext.MainWindow.Search | Add-Member -MemberType ScriptMethod 'Search' {
param(
$Text
)
#清空当前值
if($QQContext.MainWindow.Search.Box.Value)
{
$QQContext.MainWindow.Search.Button.Click()
}
$QQContext.MainWindow.Search.Box | Set-QQEditTextByCopy -Text $Text
}
}
######################
##从任务栏弹出QQ主窗口
######################
function Show-QQ
{
# QQ 进程
$QQContext.Process = Get-Process -Name 'QQ'
# 当有多个用户登录到时,其它用户的CPU为空,不为空的为当前用户对应的explorer
$explorer = Get-Process 'explorer' | where {$_.CPU} | Select-Object -First 1
#任务栏
$taskBarWindow = Get-UiaWindow -ProcessId $explorer.Id -Class 'Shell_TrayWnd'
$QQContext.TaskBar = $taskBarWindow | Get-UiaToolBar -Name '用户显示的通知区域' | Get-UiaButton -Name '*qq*'
$QQContext.TaskBar.Click()
# 刷新主窗口
Get-QQ
}
######################
##新建QQ群会话
######################
function New-QQGroupTalk
{
param(
[string]$ContactName
)
#先点击“微博”,可以避免组合好友列表折叠起来
$QQContext.MainWindow.HubMenus.Weibo.Click() | Out-Null
#再点击“QQ群组”选项卡
$QQContext.MainWindow.HubMenus.Group.Click() | Out-Null
#打开会话
$QQContext.MainWindow.Window |
Get-UiaControlByChildrenIndex -IndexChain @(4,1,3,0,0,0,0,1) |
Get-UiaListItem -Name $ContactName |
Invoke-UiaControlClick |
Invoke-UiaControlClick -DoubleClick | Out-Null
sleep -Milliseconds 100
#聊天窗口
$talkWindow = Get-UiaWindow -Class 'TXGuiFoundation' -Name $ContactName
#消息框
$editBox = $talkWindow |
Get-UiaControlByChildrenIndex -IndexChain @(1,0,0,0,2,3,0) |
Get-UiaEdit
#发送消息按钮
$sendButton = $talkWindow | Get-UiaButton -Name '发送(&S)'
#关闭窗口按钮
$closeButton = $talkWindow | Get-UiaControlByChildrenIndex -IndexChain @(2,2)
#发送消息窗口
$talkObj = [PSCustomObject]@{
Window = $talkWindow
EditBox = $editBox
SendButton = $sendButton
CloseButton = $closeButton
}
#发送消息方法
$talkObj | Add-Member -MemberType ScriptMethod 'SendMessage' {
param(
[string]$Text
)
$this.EditBox | Set-QQEditTextByCopy -Text $Text
$this.SendButton | Set-UiaFocus | Invoke-UiaControlClick | Out-Null
}
return $talkObj
}
######################
#测试代码
######################
#初始化QQ上下文
Get-QQ
#会话窗口
$talkWindow = New-QQGroupTalk -ContactName 'PowerShell交流群'
#发送消息
$talkWindow.SendMessage("PowerShell中文博客:https://www.pstips.net")
本文链接: https://www.pstips.net/send-message-to-qq-group.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

不错,晚上回家一定学习。我觉得这个挺好的。
所以我简单的写了个小函数 Get-UiaControlByChildrenIndex,能根据控件的索引路径来查找,避免走弯路。不好意思,想问一下,你怎么知道哪个控件的索引路径是多少???
这要用到你个工具UISpy,你可以在网上找下。
已在微博发了私信!
执行到”SendMessage“总是有问题
有问题,极有可以是控件没有找对,或者权限问题。你用UISpy调试一下控件树。
咱有技术群吗,方便加一下吗
3q
学习一下 感谢分享
为啥现在Set-UiaFocus和$element.Focus跟失效了一样……至少对于QQ如此。
对于编辑框,我发现可以用$editBox.Value=”12312312312323″的方式来获取焦点(虽然它并不能改变编辑框的值,但至少允许我ctrl+V了)
但如何获取消息框内的信息呢……尝试以各种方式发送ctrl+C未果,都是焦点的问题。右键->全部选择–>右键–>复制虽然可以,但可靠性实在值得怀疑……
好吧。其实在编辑框tab一下就好了……
那个。。我是用别的语言开发,我可以取得消息记录,群成员等信息。
已有成熟的小软件,用来监控群的消息,对于各种自定义命令做出反应,
但是还有几个问题。。
1。无法取得聊天的图片内容。
2。群成员,是否在线,是否手机在线,等,就是人名前的小图标,头像小图标,这个也无法取到。
这些我试着在UISPY里,根本连位置都无法检测到。。好困惑。。