RPA利器UiBot开发指南https://www.cnblogs.com/zxx193/p/11857555.html

怎甘沉沦 提交于 2019-12-04 20:04:12

UiBot官方开发者指南 >>

 

一、简介

1.什么是RPA?

Robotic Process Automation,中文翻译为机器人流程自动化,简称RPA。

RPA是软件机器人,用来完成计算机上重复的工作

 

2.UiBot是什么?

UiBot是一种RPA平台

 

3.RPA平台组成部分

1.开发工具:制作、运行、调试软件机器人

2.运行工具:普通用于运行已有流程,查阅结果。

3.控制中心:对多台PC上的机器人集中控制(分发流程、设定启动条件等)

Creator把流程先上传到Commander,再由Commander统一下发给各个Worker,并统一指挥各个Worker执行流程

                                       UiBot的三个组成部分

 

 

二、基本概念

流程 > 流程快 > 命令 > 属性

1.流程:UiBot流程是一连串的执行动作,以流程图的方式显示,包含一个文件夹。

 

 

2.流程图:

包含“开始”、“结束”、“流程块”和“判断”四种元素,用箭头连起来。

 只能有一个“开始”元素,可以有多个“结束”元素,可以有多个“判断”元素,至少一个“流程块”。

一个流程分多个步骤,每个步骤用流程块来描述(冰箱打开 -> 装进大象 -> 关上冰箱)。

推荐把逻辑独立的封装成一个流程块,留个流程块最好不要超过20个,多个沟通起来困难。

 

 

3.可视化视图

命令:把一个步骤具体细化成命令去执行,如:模拟鼠标、键盘操作,对窗口、浏览器操作等

属性:细化描述具体的命令

 

4.源代码视图

 

 

 

 

5.小结

这一章学习了四个概念:流程、流程块、命令、属性。还看到了三种视图:流程图、可视化视图、源代码视图。它们之间的关系如下图所示:

 

流程包含多个流程块,流程块包含多个命令,命令包含多个属性。流程图是流程的展现,可视化视图和源代码视图都是流程块的展现。

 

6.进阶:流程图的输入和输出

流程图中的变量,其作用域也仅限于当前流程中,在流程块里面是无法直接使用的。

当一个流程块开始运行的时候,可以把一个值(可以是变量或者表达式)“输入”到流程块中;而当一个流程块运行结束的时候,也可以把一个值“输出”到流程图中的某个变量中。还可以在流程图中加入一个“判断”,根据某个值,来决定究竟后面要找哪条路径去运行。

UiBot用到的编程语言是不区分关键字、变量名的大小写的,所以您也可以写 SELF.INPUTself.input,或者 RETURN <输出值> 等。

                                               流程图的属性栏

 

如下图所示,“判断”元素有两个出箭头,一个标有yes,一个标有no,当其属性中的“条件表达式”为真时,沿着yes箭头往后运行,否则,沿着no箭头往后运行。

 

流程图输入和输出的具体用法:

 

我们首先选中“流程块1”,在其“输出”属性中,填写一个变量名,假设是X;然后选中“流程块2”,在其“输入”属性中,填写同样的变量名(不区分大小写)。这样,通过变量X,就把“流程块1”的输出和“流程块2”的输入连接起来了。如下图所示。 这个变量X仅在当前流程图中有效,其作用仅仅是把两个流程块连接起来。在流程块1和流程块2中,均无法直接使用X来设置或者获取其值。

                 通过同一个变量,连接流程块1的输出和流程块2的输入

 

如何让流程块1输出,又如何让流程块2输入呢?

我们先点击“纸和笔”图标进入流程块1,只需要插入一条“获取系统时间”和一条“格式化时间”命令(在“时间”分类下),并把“格式化时间”中的“时间”属性设为“获取系统时间”的结果,即可得到当前时间,并以容易阅读的格式保存在变量sRet中。 然后,再插入一条“跳出返回”命令(在“词法语法”分类下),并把sRet设为返回值,即可让流程块1正确输出。如下图所示。为了方便读者理解,图中同时列出了这个流程块的可视化视图和源代码视图,读者可根据掌握程度任选其一。

                                            在流程块1中输出当前时间

再点击“纸和笔”图标进入流程块2,只需要插入一条“输出调试信息”命令,并把“输出内容”属性设为Self.Input(不区分大小写)即可。如下图所示。同样,我们也列出了这个流程块的可视化视图和源代码视图,以方便理解。

                          在流程块2中输出调试信息,信息来自于流程块1

回到流程图界面,然后点击“运行”按钮,即可看到运行结果。注意,由于流程块2需要获得流程块1的输出,所以,在流程图中运行的结果是正确的。虽然流程块2也可以单独运行,但在单独运行时,由于缺乏流程块1的输出,结果可能会有不同。

 

 

三、界面元素

 1.什么是界面元素?

  鼠标下面都是一个小的图形部件,我们把这些图形部件称为“界面元素”。

   在UiBot中,界面元素的作用,就是作为“有目标”的命令中的目标使用。

 

2.目标选取

点击目标”命令和“选择目标”按钮

用“目标选择器”选中开始菜单按钮

“目标”属性的值

{"wnd":[{"app":"explorer","cls":"Shell_TrayWnd"},{"cls":"Start","title":"开始"}]}

 

3.目标编辑

目标常见错误:

  • 无论如何移动鼠标,都无法使遮罩恰好遮住要作为目标的界面元素(通常是遮罩太大,遮住了整个窗口)
  • 遮罩可以恰好遮住界面元素,但用生成的数据查找目标时,发生了:
    • 错选:找到界面元素不是我们选的
    • 漏选:界面元素存在,却找不到

                    修改目标

 

                                     目标编辑器

 

0:这是目标的上级界面元素  1:是目标界面元素,程序逐级从上往下查找。

 

  • 不理解的特征名称,比如cls、aaname等,暂时不管它们;
  • 善用通配符 *,代表“匹配任意内容”。如界面元素title特征的值是“姓名:张三”,“张三”可能变,但“姓名:”不变。所以,可以用title: "姓名:*"来作为特征,而不是把这条特征去掉;
  • 去掉特征的时候要慎重。去掉特征可以减少漏选,但会增加错选。流程运行时漏选易发现,错选不易发现。

大多数的“有目标”命令在找不到目标时会报错,除非:(1)判断了目标是否存在 (2)用Try…Catch捕获异常。

程序错选的时候,UiBot并不知道,还会继续往下运行。

 

提醒:不同操作系统、浏览器上,同样的界面元素特征可能不一样。

 

 所以,在用UiBot制作流程,并且在别人的计算机上使用的时候,请尽量保持开发环境和生产环境的一致性,以减少不必要的错误。

 

4.进阶

遮罩选取目标常见问题:只能遮罩选取整个窗口,不能具体选中目标界面元素。

 

如何正常选取?

1.Chrome浏览器:

Chrome浏览器需要安装扩展程序UiBot Native Message Plugin”,并启用。

 

 推荐大家在RPA流程中还是使用原生的Chrome浏览器IE浏览器(360安全浏览器、QQ浏览器等容易出错)

 

2.跨域网页

网页中通过iframe嵌套了另一个域名下的网页(不同的二级域名或顶级域名),Chrome浏览器处于安全考虑,禁止对引用的网页访问,如元素选取,执行JS等,无法自动化操作。(IE可以)

解决办法:

(1)使用IE浏览器

(2)通过启动参数命令,来关闭Chrome的安全设置

右键点击Google Chrome图标,选择 属性->快捷方式,在“目标”一栏填入启动参数,具体格式如下:<Chrome安装路径> --disable-web-security --user-data-dir=用户数据目录。比如,我们的Chrome安装在C:\Program Files (x86)\Google\Chrome\Application\chrome.exe下,用户数据目录为D:\temp,那么套用格式,我们在Chrome目标窗口应填入C:\Program Files (x86)\Google\Chrome\Application\chrome.exe --disable-web-security --user-data-dir=D:\temp,如下图:

                        Chrome关闭安全设置

在目标后添加(双引号后面): --disable-web-security --user-data-dir=D:\temp

 

在经过以上操作后,我们再打开Chrome,会看到Chrome地址栏会有如下的提示,并且安装的扩展程序也消失不见了。不要着急,这是因为Chrome的用户数据目录发生了变化,只要重新安装UiBot的Chrome扩展程序,即可自动化操作。

                                                                  Chrome关闭安全设置后打开显示

经过以上设置,Chrome即可支持跨域访问。

 

3.SAP客户端程序

SAP客户端程序需要在设置中打开脚本支持,才能正常选取。我们以SAP 710客户端为例:

  1. 打开SAP客户端程序,进入登录主界面;
  2. 输入rz11事务码并进入相应界面;

                           SAP输入事务码

  1. 在事务界面输入sapgui/user_scripting,并点击display

                                                        rz11事务界面

  1. 查看Current Value当前值选项,如果为TRUE则已经开打选项,不需要做任何改动;如果为FALSE则需要点击Change Value改变此处为TRUE;

                                             sapgui设置界面

  1. 点击设置按钮,选择Options项;

                                                      SAP客户端设置选项

  1. 切换到Scripting选项卡,勾选“Enable Scripting”选项,并取消勾选“Notify When a Script Attaches to Running Man GUI”和“Notify When a Script Opens a Connection”选项。

                          SAP客户端Scripting选项卡设置

设置完成后,即可象普通的Windows软件一样,用UiBot对SAP客户端进行界面元素的获取和操作。除了前文中介绍的“鼠标点击”、“键盘输入”等操作之外,我们来看一个新的例子,用UiBot自动设置单选框的内容:

在“界面元素”类的命令下,找到“设置元素勾选”命令,拖动插入到组装区。按下“查找目标”,可以看到UiBot的界面元素选择遮罩可以准确的遮住SAP客户端中每个单选框的位置。选中我们关注的单选框,并在命令属性栏的“是否勾选”选择“是”即可。如图所示:

SAP客户端Scripting选项卡设置

运行此流程,即可看到SAP客户端的单选框被UiBot自动设置为“Display inbound call”一项。

 

4.JAVA程序

UiBot支持Swing、AWT、JNPL、Applet等多种Java应用程序。除Swing以外,其他Java程序都需要安装Java扩展程序。

可以按照如下步骤去安装Java扩展程序:

  1. 打开UiBot Creator,随便选择一个流程。在菜单中选择“帮助”->“安装Java扩展”;

  2. 安装成功之后,UiBot Creator将会有对应的安装成功提示出现。需要注意的是,如果需要操作的Java程序是以管理员权限进行安装,那么同样需要以管理员权限启动UiBot Creator,才能顺利安装Java扩展程序。

安装后,即可象普通的Windows软件一样,用UiBot对Java程序进行界面元素的获取和操作。

 

5.进阶:网页目标

                                                               网页目标:百度主页的二维码

 wnd信息标明了这个网页所在的浏览器窗口,html信息才是网页上的界面元素的关键信息。

  • html:代表这是一个网页界面元素;
  • url:对应浏览器地址栏中显示的URL,不参与元素特征匹配。仅在“绑定外部浏览器”命令中(在“浏览器”类命令中可以找到)用到,用于选择想要绑定的浏览器活动标签页;
  • title:与url类似,对应浏览器标签页的标题,不参与元素特征匹配,也仅在“绑定外部浏览器”命令中使用;
  • tagName:html标签类型(div、a、input等);
  • attrMap:对界面元素详细的html描述;
  • index:一般起辅助作用,说明在满足特征条件情况下,元素出现的顺序。UiBot的index是从数字1开始的,当index没有填写或取0时,则会选择第一个出现的元素。

 

 

实例:获取产品月销量

 

具体步骤:

  1. 从UiBot Creator的命令区选择“获取元素文本”命令,如下图:

                                                     获取元素文本命令

 

  1. 在“获取元素文本”命令上点击“查找目标”按钮,并选择销量数字,如Intel i5 8500页面的“98”,如下图:

                                               选中需要获取的文本

 

  1. 用“输出调试信息”命令查看抓取到的值(当然,也可以用于其他用途,如转换成数字、保存到Excel表格等,本文暂不赘述其他用途),如下图:

                              查看抓取的内容

看起来,好像工作得很好,毫无问题的获得了Intel i5 8500的月销量:98。但是,如果我们在其他商品上再去运行这个流程(使用Chrome浏览器,只需切换页面的标签即可,UiBot始终会在激活的标签工作),就会发现出问题了。

                                          在其他商品上运行流程

可以看到,在等待一定时间之后,UiBot最终因为没有找到目标而抛出了异常。那么,问题到底出在什么地方?我们应该如何做,才能让UiBot顺利找到目标呢?

 

点击“获取元素文本”命令,查看命令的属性,并具体打开“目标”属性进行查看,如下图:

细心的读者可能已经发现了:原来"aaname"这条特征已经被固定在“98”了。这显然是不合理的:我们本来就是为了获取销量,如果把销量的数值98也加到特征里面,那是毫无意义的!因为销量一旦发生变化,特征就无法匹配了,造成“漏选”的问题。怎么办呢?我们可以很自然的想到:取消aaname特征的勾选状态,或把aaname的特征采用"*"进行通配,即可跳过这条造成“漏选”的特征。如下图:

                                          修改“aaname”的特征为通配符

请注意,这里不必纠结上面图片框里显示的98,那只是一张参考图,在实际查找目标的时候不会起到任何作用。也不必纠结titleurl这两条特征,因为前文已经提到,这两条特征也不会参与到查找目标的过程中。

修改完成之后,再次运行这个流程块,看看是否能正确获取其他商品的月销量。如下图:

                                    修改“aaname”特征之后的运行

奇怪的事情发生了,之前的异常确实没有出现,并且获取到了内容。但是并不是我们想要的“77”,而是“月销量”几个字,这是怎么回事呢?

我们观察一下页面上的内容,发现修改“aaname”之后,虽然不会发生“漏选”,但由于文字“月销量”的特征和“77”完全一致,造成了“错选”。仔细查看即可发现,“月销量”文字和“77”的tagName、attrMap等特征完全一样,好比是一个户口本里的同一家人,已经无法区分了。怎么办呢?可以使用"index"特征来定位他们的不同。上文提到,UiBot的index是从数字1开始的,当index没有填写或取0时,则匹配第一个。从页面上看,“月销量”这个元素在销量数字的前面,如果它是第一个,那么销量数字就应该是第二个,因此,我们猜测,当的index取2的时候,就可以找到销量数字了。不妨填上试一下。

                                                     修改“index”特征的值

现在验证一下。在UiBot Creator工具栏上,点击“运行”按钮,直接运行当前的流程块。可以看到,在其他商品的页面上,也可以正确的拿到了其月销量数据了。

实际操作中,多多尝试和总结经验。

 

 

四、无目标命令

1.为什么没有目标?

UiBot所在的系统和目标不在统一系统中,无法操作目标界面元素。

虚拟机和远程桌面,如:Citrix、VMWare、Hyper-V、VirtualBox、远程桌面(RDP)、各种安卓模拟器(如靠谱助手)等

解决办法:可以把UiBot和流程涉及到的软件,都安装在虚拟机里,或者远程计算机里。

 

 基于DirectUI的软件:元素是被画出来的,UiBot无法找到。

 

 游戏:元素是画出来的,界面变化快,时效性要求高,RPA对游戏效果不好。游戏推荐按键精灵。

 

2.无目标命令

                               有目标和无目标的命令

 

最重要的是“模拟移动”:设置坐标位置 - 模拟移动 - 模拟点击 - 输入文本 

Windows坐标理解为第4象限,坐标x:200, y:300,x轴是距离屏幕左边的水平方向的距离,y轴是距离屏幕上面的垂直方向的距离。

                    Windows的屏幕坐标系

坐标保存在BotScript语言的字典中,字典可以存放多个值,变量名为pnt,则使用pnt["x"]pnt["y"]即可得到坐标的x和y两个值。

固定坐标情况很少,一般都会有变化的,一般推荐使用其他命令根据某种特征,先找到界面元素的坐标,然后把坐标当做变量穿给无目标命令。

在UiBot中,无目标命令的最佳拍档,是图像命令。

 

3.图像命令

UiBot Creator里面列出的“图像”类命令

“查找图像”命令:指定一个图像文件,格式png(无损压缩,推荐)、bmp、jpg等,扫描查找是否在指定区域,没有则发生异常。

                         使用“查找图像”命令并指定图像和查找范围

 

                  “查找图像”命令的属性

“激活窗口”:把窗口放到最前面显示,防止被其他窗口遮挡,一般都默认是。

                                                  用“输出调试信息”查看结果

结果:

{ "x" : 116, "y" : 235 }

 

objPoint["x"] 和 objPoint["y"] 即可得到其中的x和y值

                                             用“输出调试信息”查看结果

 

“点击图像”:“查找图像”、“模拟移动”、“模拟点击”三条命令的组合

 

4.OCR命令

                        很难直接获取微信中的聊天文字

 

UiBot采用百度云OCR,使用条件:

1.联网

2.向百度付费:免费通用文字识别每天5000次,证照等识别每天500次,超过了需要购买百度服务。

3.注册百度账号:需要自己注册百度云账号 及 百度云OCR服务的账号(一般称为Access Key和Secret Key),申请方法很简单,请点击这里查看我们的在线教程

                         UiBot的OCR命令

红框里的命令类似于“图像”类中的“点击图像”、“鼠标移动到图像上”,“查找图像”命令,只不过不需要传入图像了,只需要在属性中标明要找的文字即可。

蓝框里的命令和绿框里的命令类似,只不过前者需要提供一个图像文件,后者需要提供一个窗口、以及窗口中的一个区域。

                                    选择OCR目标

 

                                 完成一条OCR命令

 

下面,再测试一下“图像特殊OCR识别”命令。所谓“特殊”,是指我们要测试的是某种特定的图像,如身份证、火车票等。假设我们在D:\\1.png文件中保存了如下的图像:

                                要进行特殊OCR的图像

 

                                         特殊OCR的属性设置

 

5.注意事项

无目标的命令,特别是它们所依赖的图像、OCR等命令,有以下的缺点:

  • 速度慢
  • 怕遮挡
  • 依赖图像文件
  • OCR需联网

 

图像、OCR命令技巧:

截图尽量小  

区域尽量小

尽量保持分辨率和缩放比列一致

如,Windows 10操作系统分辨率和缩放比例:

使用图片时用绝对路径:

推荐把图片文件放res文件夹下,用@res"1.png"表示路径,@可以自动获取前缀路径。

 

 

五、语言参考 

1.概述

UiBot是用来做RPA的编程语言,UB语言简单易用。

 

2.基本结构

UB语言是纯文本格式,UTF-8编码。

 

执行一个流程块的时候,从第一行开始执行,遇到函数定义暂时跳过,然后继续从函数结束后的一行开始执行。

 

 推荐一行只写一个语句。如果一定要写多个语句,则用冒号分隔符(:)进行分隔。

 

 需要折行,可以在任意语句中出现的逗号(,)或二元运算符(“二元运算符”的概念请参考这里)之后直接折行,一定要在其他地方折行,则用反斜杠(\)作为折行符号。例如:

Dim a= \
1

 

 注释:

单行注释://

 多行注释:

 /*

语句1

语句2

*/

 

UB语言中所有关键字、变量名、函数名均不区分大小写。

 

3.变量、常量和数据类型

  1.数据类型:整数、浮点、布尔、字符串、函数、复合型和空值。

    整数型:可以以十进制或者十六进制的方式表示,其中十六进制需加前缀 &H 或 &h

    浮点数:可以用常规方式或者科学计数法表示。如 0.01 或者 1E-2 或者 1e-2 均代表同一个浮点数。

    布尔型:True 或 False不区分大小写

    字符串:一对双引号(") 或 一对单引号(')包含,\t 代表制表符,用 \n 代表换行,用 \' 代表单引号,用 \" 代表双引号,用 \\ 代表反斜杠本身。

                   字符串中间可以直接换行,无需增加任何其他符号,换行符也会作为字符串的一部分。

   

   用前后各三个单引号(''')来表示一个长字符串。在长字符串中,可以直接写回车符、单引号和双引号,无需用 \n\' 或者 \"

  

   函数型的值只能是已经定义好的函数

   复合型:数组、字典等

   空值型: Null,不区分大小写

a = 1           // a是整数型变量
a = &HFF        // a还是整数型变量
a = True        // a是布尔型变量。作为动态类型语言,a的类型可以随时变化 
a = FALSE       // a是布尔型变量,注意True和False都不区分大小写
a = 'UiBot'     // a是字符串型变量
a = "UiBot
RPA"            // a是字符串型变量,字符串中可以换行
a = null        // a是空值型变量,可以写为Null、NULL或null(不区分大小写)

 

 

2.变量和常量

变量定义:

Dim 变量名

 

定义变量并赋初值:

Dim 变量名=值

定义多个变量:

Dim 变量名1 = 值1, 变量名2
Dim 变量名1 = 值1, 变量名2 = 值2

 

 

标识符:有命名的东西(例如:变量、常量、函数等)

标识符以英文字母或_开头,可以包含数字、UTF-8编码中的其他语言字符(如汉字),变量名不区分大小写。

UB语言变量必须定义(除了For语句中的循环变量、Try语句中的异常变量、函数参数等)。

 

局部变量:函数内定义和使用

全局变量:函数外任意位置定义,全局使用。

 

3.复合类型

数组:

[值1, 值2, 值3 ]

字典:

{ “名字1”:值1, “名字2”:值2, “名字3”:值3 }

 

名字只能是字符串,值可以是任意类型

 

索引使用方括号[],多维数组或字典中的数组:

变量名[索引1][索引2]

 

Dim 变量 = [486, 557, 256]                      // 变量可以用中文命名,初值是一个数组
a = 变量[1]                                     // 此时a被赋值为557
变量 = {"key1":486, "key2":557, "key3":256}     // 变量的类型改为一个字典
a = 变量["key1"]                                // 此时a被赋值为486
变量["key4"] = [235, 668]                       // 往字典中增加一个新值,可以是一个数组
//此时,字典中的内容为 {"key1":486, "key2":557, "key3":256, "key4":[235, 668]}
a = 变量["key4"][0]                             // 此时a被赋值为235

 注:数组索引只能是整数,0开始。字典索引只能是字符串类型。

 

4.运算符和表达式

 

 表达式:变量、常量和值用运算符和圆括号 ( ) 连接到一起

Not 是一元运算符

 - :一元运算符,也可以用作二元运算符

 其他都是二元运算符

注:=:出现在括号()内表示判断,单独语句表示赋值。

 

 表达式常用于赋值语句,可以给某个变量赋值,其形式为:

变量名 = 表达式

 

 

数组、字典是引用类型,引用传递。

引用类型:
a = [486, 557, 256]     // a是一个数组
b = a                   // b是a的“别名”
b[1] = 558              // 改变b里面的值,a里面的值也会跟着改变
c = a[1]                // 此时c的值是558,而不是原来的557

变整数类型:
a = 557                 // 此时a被赋值为557(变为整数型)
b = a                   // 此时b里面的值也是557,但和a分别保存
b = 558                 // b里面的值发生改变,a的值不改变
c = a                   // 此时c的值仍然是原来的557,因为a不是字典、数组

 

 

5.逻辑语句

(1).条件分支语句

If 条件
    语句块1
End If
If 条件
    语句块1
Else
    语句块2
End If
If 条件1
    语句块1
ElseIf 条件2
    语句块2
Else
    语句块3
End If

 

示例:

// Time.Hour() 可以取得当前时间中的小时数
// TracePrint() 可以把指定的内容输出到UiBot的输出栏中

If Time.Hour() > 18             // 取得当前时间中的小时数
    TracePrint("下班时间")      // 如果大于18,则执行这里的语句
Else
    TracePrint("上班时间")      // 如果不满足前面的条件,则执行这里的语句
End If

 

 

(2).选择分支语句

根据一定的条件,选择多个分支中的一个。先计算Select Case后面的表达式,然后判断是否有某个Case分支和这个表达式的值是一致的。如果没有一致的Case分支,则执行Case Else(如果有)后面的语句块。

Select Case 表达式
    Case 表达式1, 表达式2
        语句块1
    Case 表达式3, 表达式4
        语句块2
    Case Else
        语句块3
End Select

 

示例:

Select Case Time.Month()            // 取得当前时间中的月份
    Case 1,3,5,7,8,10,12            // 如果是1、3、5、7、8、10、12月
        DayOfMonth = 31             // 当月有31天
    Case 4,6,9,11                   // 如果是4、6、9、11月
        DayOfMonth = 30             // 当月有30天
    Case Else                       // 如果是其他(也就是2月)
        DayOfMonth = 28             // 当月有28天(不考虑闰年的情况)
End Select
TracePrint(DayOfMonth)

 

 

(3).条件循环语句

在UB语言中,使用Do…Loop语句来实现条件循环,即满足一定条件时,循环执行某一语句块。Do…Loop语句有以下五种不同的形式,用法较为灵活:

  1. 前置条件成立则循环:先判断条件条件成立则循环执行语句块,否则自动退出循环。
Do While 条件
    语句块
Loop
  1. 前置条件不成立则循环:和前一条相反,条件成立则退出循环,否则循环执行语句块。
Do Until 条件   //Until:到...为止
    语句块
Loop

 

  1. 后置条件成立则循环:先执行语句块,再判断条件条件成立则继续循环执行语句块,否则自动退出循环。
Do
    语句块
Loop While 条件

 

  1. 后置条件不成立则循环:先执行语句块,再判断条件条件成立则自动退出循环,否则继续循环执行语句块。
Do 
    语句块
Loop Until 条件

 

  1. 无限循环:该循环语句本身不进行任何条件的判断,需要在语句块中自行做判断,如果语句块中没有跳出循环的语句,则会无限的执行该循环
Do
    语句块
Loop

 

示例:

Do Until Time.Hour() > 18              // 判断当前时间中的小时数,只要不大于18就循环
    TracePrint("还没有到下班时间")      // 每次循环,都会执行这里的语句
    Delay(1000)                        // 每判断一次,休息一秒钟
Loop
TracePrint("下班时间到啦")              // 如果大于18,则跳出循环,执行这里的语句

 

 

(4).计次循环语句

计次循环语句主要用于执行一定次数的循环,其基本形式为:

For 循环变量 = 起始值 To 结束值 Step 步长
    语句块
Next

 

起始值结束值步长都只允许是整数型或者浮点数型;步长可以省略,默认值为1。变量从起始值开始,每循环一次自动增加步长,直到大于结束值,循环才会结束。

 

在计次循环语句中,循环变量可以不用Dim语句定义,直接使用,但在循环结束后就不能再使用了。

Dim count = 0               // 定义变量count
For i=1 To 100              // 每次循环,变量i都会加1。这里变量i不需要定义
    count = count + i
Next
TracePrint(count)           // 这里会显示1+2+3+…+100的结果,即5050

 

 

(5).遍历循环语句

遍历循环语句可以用于处理数组、字典中的每一个元素。遍历循环语句有以下两种形式:

For Each 循环变量 In 数组或字典
    语句块
Next

 

在这种形式的循环语句中,会自动遍历数组、字典中的每一个值,并将其置入循环变量中,直到遍历完成为止。

或者:

在这种形式的循环语句中,会自动遍历数组、字典中的每一个索引和值,并将其分别置入循环变量1、循环变量2中,直到遍历完成为止。

 

和计次循环语句类似,在遍历循环语句中,循环变量可以不用Dim语句定义,直接使用,但在循环结束后就不能再使用了。

例如:

Dim days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] // 定义数组型变量days
Dim count = 0   
For Each i In days             // 每次循环,变量i的值分别为days中的每个值 
    count = count + i          // 把数组中的每个值依次加起来
Next
TracePrint(count)              // 这里会显示一年中每个月的天数的累加和,即365

 

 

(6).跳出语句

Break:只能出现在条件循环、计次循环或遍历循环等循环语句的内部语句块中,其含义是立即跳出当前循环。

Continue:只能出现在条件循环、计次循环或遍历循环等循环语句的内部语句块中,其含义是立即结束当前循环,并开始下一次循环。

Exit:自动结束整个流程 (不是当前流程块)

例如:

Dim days = { '一月':31, '二月':28, '三月':31, 
             '四月':30, '五月':31, '六月':30, 
             '七月':31, '八月':31, '九月':30, 
             '十月':31, '十一月':30, '十二月':31 }  // 定义字典型变量days

For Each i,j In days            // 每次循环,变量i, j分别为days中每个名字和值
    If j Mod 2 = 0              // 如果j是偶数
           Continue             // 结束本次循环,开始下一次循环
    End If
    TracePrint(i)               // 把days中的名字(其值不是偶数)显示出来
Next

 

 

6.函数

函数的定义和调用没有先后关系,可以先出现调用,再出现定义。但函数必须定义在全局空间中,也就是说,函数定义不能出现在其他函数定义、分支语句、循环语句下面的语句块中。

  • 无参数的函数
Function 函数名( )
    语句块
End Function
  • 有参数的函数
Function 函数名(参数定义1, 参数定义2)
    语句块
End Function

在函数定义中,要退出函数并返回,采用以下写法:

Return 返回值

 

Function Add(x, y=1)        // 定义了两个参数的函数,第二个参数有默认值
    Return x + y            // 返回值为x+y的值
End Function

 

调用函数的格式如下:

返回 = 函数名(表达式1, 表达式2)

或者

函数名(表达式1,表达式2)

 

按照第一种格式调用,可以指定一个变量作为返回,当函数调用完成后,函数的返回值会自动赋值给这里的返回变量,调用者可以通过返回值,了解到函数调用的情况。此时,必须在被调用的函数名后面加圆括号。而当按照第二种格式调用时,调用者不需要返回值,则可以省略圆括号,使语句更符合自然语言习惯。

 

当调用时,相当于对函数中的参数进行了一次赋值运算,用表达式的值对其赋值。与赋值运算的规则相同,当表达式为一个独立的(没有使用任何运算符计算)数组、字典时,赋值操作只赋值其引用,也就是说,只是为变量增加一个“别名”。

 

调用函数时,传入的表达式的数量可以少于参数的数量,如果某个参数没有传入值,或者传入值为Null,则采用其默认值,如果连默认值也没有,则其值自动为Null

a = Add(100)            // 调用Add函数,第二个参数取默认值1,所以a的值是101
b = Add(100, 200)       // 调用Add函数,指定了两个参数,所以b的值是300
Add 100, 200            // 调用Add函数,不关心返回值,所以可以不写括号

 

当函数定义完成后,其名称可以作为一个函数类型的常量使用,也可以把函数名称赋值给某个变量,用这个变量也可以调用这个函数。

例如,对于上面定义的函数Add,可以按照如下的方式使用:

Dim Plus = Add
TracePrint Plus(100, 200)   
// 相当于先调用了Add函数,再用其返回值调用了TracePrint函数,结果是300

 

 

7.其他

(1)多模块

UB语言支持多模块,可以用其他语言实现扩展模块,并在当前流程块中使用。目前支持以下几种类型的模块:1)UB语言的流程块;2)Python语言的模块;3)C/C++语言的模块;4).Net的模块;5)Lua语言的模块。不同的模块有不同的扩展名,去掉扩展名以后,剩下的文件名就是模块的名字。比如某个Python语言的模块,文件名为Rest.py,则其模块名为Rest。

在UB语言中,采用以下方式导入一个模块:

Import 模块名

注意这里的模块名的书写规则和变量名一致,不需要采用双引号,也不需要加扩展名。如Import Rest。UiBot在编译和运行时会自动按照Lua语言模块、C语言模块、.Net语言模块、Python语言模块、UB语言流程块的先后顺序,依次加上相应的扩展名进行查找。在Windows中,由于文件名不区分大小写,所以Import语句后面的模块名也可以不区分大小写。在其他操作系统中,需要注意模块名的大小写要和文件一致。

每个导入的模块,都会被放置在一个与模块名同名的“命名空间”中,可以通过下面这种方式来调用导入模块中的函数:

命名空间.函数名

对于Python、Lua语言的模块,只会保留其中的全局变量定义和函数定义,其他内容都会被忽略。对于C语言的模块和.Net模块,只能调用其中定义的函数。

 

如果要导入一个UB语言的流程块,则需要导入和被导入的流程块文件在同一个目录下。

导入UB语言的流程块之后,既可以调用被导入的流程块中定义的函数,又可以直接以流程块的名字作为函数名,直接运行这个流程块中的所有命令。

ABC()

 

例如,有一个流程块 ABC.task。在其他流程块中Import之后,直接采用下面的格式即可直接调用ABC.task(相当于运行了ABC.task这个流程块):

ABC.test()

 

 

(2)异常

作为动态类型语言,有很多错误在编译时难以检查,只能在运行时报错。而且,由于UiBot不强调运行速度,而更强调运行的稳定性,也会在运行时加入比较多的检查。当出错的时候,比较合适的报错手段是抛出异常。 比如,对于有目标命令(“有目标命令”的概念可以参考这里),在运行的时候,如果到了超时时间都不能找到目标,就会自动抛出一个异常。

除了自动抛出的异常之外,在流程块中,还可以采用Throw语句抛出一个异常:

Throw 字符串

 

在抛出异常时,可以把异常相关信息以字符串的形式一起抛出,也可以省略这个字符串。

如果在流程块中没有对异常进行处理,当出现异常时,整个流程都会终止执行,并且把异常相关信息显示出来。如下图所示:

                                          流程运行的时候出现异常

 

如果不希望流程在发生异常的时候终止,可以采用以下语句对异常进行处理:

Try
    语句块
Catch 变量名
    语句块
Else
    语句块
End Try

 

如果在Try后面的语句块中发生了异常,会跳到Catch后面的语句块中执行。如果在Try语句块中没有发生异常,且定义了Else语句块(当然,也可以省略Else语句块),则会跳到Else语句块中执行。

Catch语句后面的变量名可以省略。如果不省略,可以不用Dim语句提前定义,当发生异常时,这个变量的值是一个字典,其中包含“File”、“Line”和“Message”三个字段,分别代表发生异常的文件名、发生异常的行号、异常包含的信息。

 

六、编写源代码

1.基本规则

UiBot的源代码视图遵循以下规则:

  • 用一个源代码文件来表示一个流程块,源代码文件的扩展名默认是.task
  • 用函数调用来表示一条命令
  • 用函数调用时传入的参数,来表示命令的属性
  • Dim语句来定义变量

 

从图中不难看出,“启动IE浏览器”的命令在源代码视图中实际上是对函数WebBrowser.Create的调用;启动IE浏览器时设置的各项属性,都是函数调用中的变量,如"about:blank"等;命令中使用到的变量,需要用Dim语言定义。

                                    可视化视图和对应的源代码视图

 

UiBot支持的命令非常丰富,在源代码视图中,这些命令都使用函数来表示。所以,UiBot实际上在UB语言的基础上,内置了一个很大的函数库。

其中,最常用的一部分函数是没有命名空间的,如Delay函数;

其他函数都是包含一个命名空间的,如前面例子中的WebBrowser.Create函数,其命名空间是WebBrowser。对于有命名空间的函数,大部分都是通过UB语言中的多模块机制,利用一个模块中实现的,所以在使用前需要先用Import语言导入相应的模块,例如WebBrowser.Create函数,在使用前需要写Import WebBrowser

当然,还有几个基础功能,其命名空间是会自动Import的,就不需要我们再做一次Import了,包括MathLogJson等。

 

UiBot支持的全部命令,其文档可以参考这里。在本文中,我们仅列出目前版本中已支持的主要命名空间及其功能概述,供读者参考。如对其中某个命名空间的功能有兴趣,再查阅文档不迟。注意,如前文所述,UB语言中的各种名字、关键字都不区分大小写,所以下表中列出的各个命名空间,都可以按全大写、全小写或各种大小写混合的方案进行书写。

 

比如,我们对Mouse下面的功能感兴趣,一种方法是查阅文档,看看这个命名空间下面有哪些函数,每个函数有哪些参数。另外,如果您的手已经放在键盘上了,还有另一种更快捷的方法,如下所述:

  1. 在UiBot Creator的源代码视图中,随便找一个空行,然后键入Mouse(其实都不需要完整输入,只需要输入首字母m,即可自动联想到相关的关键词,按上下箭头选择,并按回车确认即可)
  2. 键入一个.符号,此时,会自动列出Mouse命名空间下的所有函数
  3. 继续按上下箭头选择,每个选中的函数,都会出现其功能的简要说明,按回车确认要用的函数
  4. 再键入一个左括号(,此时,会自动列出这个函数的参数,并显示第一个参数的说明
  5. 此后,每输入一个参数,按逗号进行参数分隔后,会自动切换到后续参数的说明

上述过程大致如下图所示:

 

2.有命令目标

    

                                  “点击目标”操作的源代码视图

 

第一行,以 # 符号开头,可以简单的认为是一种特殊的注释,对流程的运行没有影响,可以省掉。其实,在UiBot Creator中用浅灰色显示,也是建议您不要纠结于此。

第一行之后的内容其实是一个函数调用,调用的函数是Mouse.Action,这个函数包含5个参数。但实际上,只有第一个参数是必须的,后面的参数都可以省略。我们不妨把可以省略的内容都去掉,只剩下下图所示的内容:

                     “点击目标”操作的源代码视图(简化后)

不难看出,函数只剩下了一个参数,这个参数是一个字典类型,代表了要点击的目标。当然,即便是这样简化,这个字典类型里面的内容也是很难手写出来的。怎么办呢?请注意,在源代码视图的上方,有“元素”、“图像”、“窗口”、“区域”四个按钮,分别还有对应的热键Alt+1、Alt+2、Alt+3、Alt+4(如下图)。由于我们需要用一个界面元素来作为命令的目标,所以,这里点击“元素”按钮。

                 

 

 

 

源代码视图上方的快捷按钮点击后,UiBot Creator的界面暂时消失,出现了“目标选择器”,也就是红边蓝底的半透明遮罩。这个“目标选择器”的用法,和可视化视图中选取目标的方法一模一样,只需要把鼠标移动到目标上,待遮罩恰好遮住目标的时候,单击鼠标左键即可。如果您对“目标选择器”的操作还不熟悉,请回头复习前文中目标选取这部分内容。

                     

                               目标编辑器的界面

选择目标之后,会弹出UiBot Creator的“目标编辑器”对话框,如下图所示。我们在前文中已经学习过如何使用目标编辑器来修改目标的特征,以避免造成目标的“错选”或“漏选”。这里的使用方法仍然与前文一致,仅有一点点细微的差别:右下角的按钮变成了“复制到剪贴板”。按下这个按钮,UiBot Creator会把目标的各个特征重新组合成一个字典类型的值,并把这个值以文本的形式复制到操作系统的剪贴板中。之后,只需要回到源代码视图,把剪贴板里的这段文本粘贴到函数调用Mouse.Action中作为参数,即可完成这条命令的编写。

不妨把这段文本粘贴到记事本里,可以看到,其内容就是描述目标的字典类型的值:

{"wnd":[{"app":"explorer","cls":"Shell_TrayWnd"},{"cls":"Start","title":"开始"}]}

 

在UiBot中书写一条Mouse.Action()函数调用,并把上述内容粘贴到圆括号里面,即可完成这条命令:

Mouse.Action({"wnd":[{"app":"explorer","cls":"Shell_TrayWnd"},{"cls":"Start","title":"开始"}]})

 

举一反三,我们试试做一点儿更多的操作。比如,把这个开始菜单按钮的图像,保存到一个图像文件里面去。用UiElement.ScreenShot函数可以完成这个任务。这个函数有两个必选的参数,第一个参数仍然是指定界面元素作为目标,第二个参数是要保存的图像文件的路径。也就是说,第一个参数和前面Mouse.Action的参数是完全一样的,把刚才复制到剪贴板的内容直接粘贴到这里就行;第二个参数写一个文件路径即可,比如"C:\\temp\\1.png"。这里有两个值得注意的细节问题:

  • 由于需要写文件,所以请注意,需要写到有权限的路径下。比如,UiBot默认不是以管理员账号启动的,所以诸如"C:\\"这样的路径就是不具有写权限的,但"C:\\temp"具有写权限。
  • 我们使用了字符串来表示文件路径,按照前文中UiBot的规定,字符串中要用转义字符\\来表示一个反斜杠\,所以路径需要写为"C:\\temp\\1.png"的格式。

保存并运行,即可看到开始菜单按钮的图像被存为一个文件。

回过头看看这段源代码,不难发现,“开始菜单按钮”这个目标被重复使用了两次,不好看。我们稍微改造一下,成为下面的样子:

Dim StartButton = {"wnd":[{"app":"explorer","cls":"Shell_TrayWnd"},{"cls":"Start","title":"开始"}]}
Mouse.Action(StartButton)
UiElement.ScreenShot(StartButton, "C:\\temp\\1.png")

这样看起来就清晰多了。

 

附录A 编程基础知识>>

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!