本篇就来兑现在《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里,根本连位置都无法检测到。。好困惑。。