RPA从小白到大师之一:AS400绿屏5250终端仿真器自动化

4 篇文章 0 订阅
2 篇文章 0 订阅

系列文章目录

综述: https://blog.csdn.net/m0_54284125/article/details/132774505
AS400: https://blog.csdn.net/m0_54284125/article/details/132778839
SAP: https://blog.csdn.net/m0_54284125/article/details/132778954
Lotus Notes: https://blog.csdn.net/m0_54284125/article/details/132779011
网页: https://blog.csdn.net/m0_54284125/article/details/132779052
Dynamics365: https://blog.csdn.net/m0_54284125/article/details/132779089
通用桌面应用: https://blog.csdn.net/m0_54284125/article/details/132779109



前言

IBM的AS400是非常经典的商用服务器,发源于上世纪70年代,历经半个世纪,至今仍在售(不过改名Power i系列了)。访问AS400, 用的是终端仿真器(Emulator)。 对仿真器做RPA工具,与常规的Windows区别还是比较大的,本篇就来全面介绍一下如何开发AS400 PC5250仿真器的RPA程序。


一、关于仿真器

1. 什么是仿真器

这里说的"仿真器",也就是俗称的“绿屏”,是一个用来连接主机的程序。长得象这样(很容易理解为什么叫绿屏,因为黑底绿字啊):
PC5250仿真器
好好的一个电脑程序,为什么要叫仿真器呢,听起来象电子行业里的设备一样。说来话长,计算机发展初期,个人电脑还没问世,大中型主机盛行,要访问主机靠的是终端(Terminal), 长这个样子:
IBM PC5250终端
终端没什么计算能力,它的作用就是连接到主机(通过同轴电缆),将用户端的输入传送给主机并将主机的反馈显示给用户。
等到个人电脑发展起来,主机与终端的关系跟着演化,主机(Host)变成了今天的“服务器”(Server),终端也由个人电脑来代替。为了兼容之前的系统,在个人电脑上开发出程序,模拟当初“终端”的行为,这个程序就是终端仿真器,简称仿真器。
那经常在IBM文档中看到的什么PC3270,PC5250仿真器又是什么意思呢?其实这些代号是当年实体终端的型号。比如上面那张图片就是5250终端。下面这个是3270终端:
IBM 3270终端
可以想象,不同的终端显示格式和样式是有区别的,所以要有对应的仿真器。不过多数是兼容的,所以并不是每一款终端都一定会有对应的仿真器。对IBM,最常见的仿真器是PC5250, PC3270. 当然了,市面上也有其它厂家生产终端,比如说DEC的VT系列也很出名,所以也有对应的VT终端仿真器
VT340

2. 常用的IBM5250仿真器

既然仿真器只是一个电脑程序,而且仿真的终端又很清楚,所以显然会有不同的公司(个人)开发不同版本的仿真器。
对于RPA, 当然是优先IBM自己的仿真器,有PCOMM和ACS两个系列。

  • PCOMM系列
    PCOMM是Personal Communications的简称。 实际上这个系列分两个阶段。在V6.0及之前,它是IBM i Access for Windows的一部分。再后来就独立出来了,目前最新版本是15.0.
    IBM i Access for Windows在2019年已经停止支持,官方说法是该程序只支持到Windows8 (以本人的实际经验,Windows 10上也是可以的,Windows11不知道是否还行)。
    上面那张绿屏的图就是PCOMM V6.0的,不同的版本外观所说是没什么变化(本人实际使用过的只到V6.0)
  • ACS系列
    ACS是Access Client Solution的简写,它是IBM最近几年新推出的基于Java的主机管理器,可以理解为对标 i Access for Windows,里面也包含有一个5250仿真器。

外观上ACS仿真器与PCOMM仿真器没什么差别, 但是在自动化(automation)支持上,二者区别还是有些区别的:

  • PCOMM 是全功能的,支持EHLLAPI和HCAL接口。而ACS并不支持HCAL。
  • PCOMM类似于开箱即用,不需要做什么特别设置就可以支持自动化;而ACS需要安装EHLLAPI增强工具。

说明:IBM提供有4种仿真器API, 除了上面提到的EHLLAPI和HCAL(正式名称叫ECL), 还有DDE和PCSAPI。基本上日常操作都是用EHLLAPI或者HCAL。

二、系统准备及避坑指南

1.ACS安装

如果你公司用的是IBM i Access for Windows 或是Personal Commulications高版本,那就没什么需要准备的。
如果是用ACS, 那注意以下几点:

  • ACS要安装1.1.8.1以上的版本(当然越新越好)
  • ACS分32bit和64bit的,安装64bit的 (道理后面会讲到)
  • ACS是基于Java的,所以需要Java JRE。Oracle几年前开始对企业用户收费了,如果你们公司没有为你购买license,IBM提供了解决方案:你可以安装第三方的免费JREJRE下载地址
  • 安装ACS EHLLAPI Enablement Tool, 下载地址

2. 关于32-bit和64-bit的坑

如果你遇到“An attempt was made to load a program with an incorrect format” 或是"无法找到dll“之类的错误提示,大概率是32位和64位程序不兼容造成的。
要理解为什么会有这个问题,要先理解32-bit和64bit的区别, 以及RPA的三个参与方:
所谓的32-bit和64-bit, 是指系统一次处理的一个字(WORD)有几个Bit(位),显然64位的效率是32位的2倍。

  • 32-bit VS 64-bit

    1. 电脑硬件(CPU)分32-bit与64-bit。现在你能用到的电脑基本上都已经是64-bit了。
    2. 操作系统分32-bit与64-bit。现在的操作系统(Windows10/11)基本上都是 64-bit的
    3. 应用程序分16-bit, 32-bit与64-bit。特别新的程序,大概率是64-bit的,但是历史遗留下来的32-bit程序也多如牛毛,甚至还有16-bit程序至今在用。(如果有谁知道8-bit的程序还在跑,请分享一下,让我们也见识一下)

    平时是不用太担心这些的,因为操作系统会向上兼容,很好地处理这些:32-bit的操作系统可以跑在64-bit的电脑上,16-bit的应用程序可以跑在32-bit的操作系统上 – 虽然这浪费了硬件投资。
    但是如果是应用程序之间打交道,这个事儿就复杂了。

  • RPA 涉及方的位数
    所谓而RPA,实质就是用一个程序A(Robot), 通过程序B(API接口), 去控制另一个程序C(在这里就是仿真器)。这里程序位数就成了重要因素。正常情况下,这三方的bit需要保证是一样的,否则传递的参数不能正常解析。
    不过一个API出来以后,后续的仿真器可能会做些特别处理,兼容之前的API, 比如说,仿真器升级到64位了,可能会开发配套的64位的API, 对之前32位的API也可能继续支持。具体情况要看官方文档。

    • ACS
      ACS原生并不支持Automation API, 它需要安装一个增强包。这个增强包里,只有EHLLAPI和PCSAPI, 并不包含HACL。基本上,这个增强包等同于i Access for Windows中的PCOMM V6.0中的部分文件(少了HACL)。可以参见IBM的官方文档
      ACS 分32-bit和64-bit. 但它还跟JRE的位数相关。现在IBM提供的32-bit的JRE只有8.0, 实际测下来32-bit的ACS并不能真正运行。要使用64-bit的JRE + 64-bit的ACS。
      但是因为ACS用的是32-bit的API, 所以开发出来的控制仿真器的程序(Robot)必须也是32-bit的. 也就是说:

      1. 如果你是用VBA写的程序, Excel必须是32-bit的, 64-bit的不行(这里Robot就是Excel)。如果你的Excel是64-bit的,要么重装32-bit的,要么改用64-bit 的PCOMM .
      2. 如果你是用VBScript写的程序,注意要强制用32-bit的解释器 (c:\windows\syswow64\cscript *.vbs), 参见IBM官方文档。否则系统默认会使用C:\windows\system32\下的解释器,它是64-bit的(现在操作系统基本都是64位的),结果就是程序无法执行,提示“ActiveX component can’t create objec”错误。
      3. 如果是用C#或其它语言开发程序,要指定编译后的程序是32-bit的。
        生成32-bit的程序
    • PCOMM

      1. PCOMM V6.0 (iAccess for Windows自带的)是32-bit的,自然也只支持32-bit的Robot。要求跟上面ACS一样 – ACS使用的API就是同一款的嘛。
      2. PCOMM V12/13/14/14没用过,但是根据官方文档,V12/13这两个版本也都还是32-bit的, 那么从道理上来说,要求跟V6.0是一样的。从V14.0开始,PCOMM改为了64-bit, 它要求Robot必须是64-bit的
        在这里插入图片描述
        在这里插入图片描述
        所以,如果你正在使用PCOMM V14.0及以上的版本:
        1. 如果你是用VBA写的程序, Excel必须是64-bit的, 32-bit的不行(这里Robot就是Excel)。而且如果使用的是32-bit的API,需要在引用dll文件时加上PtrSafe 关键字以兼容64-bit
          Declare Function pcsStartSession Lib "PCSAPI32.DLL" (ByVal buffer As String, ByVal SessionID As Integer, ByVal CmdShow As Integer) As Integer
          
        2. 如果你是用VBScript写的程序,没啥特别需要注意的,因为系统默认会使用C:\windows\system32\下的解释器,它是64-bit的。
        3. 如果是用C#或其它语言开发程序,也没有需要特别注意的, 因为默认编译后的程序就是64-bit的。

三、使用EHLLAPI编写RPA程序

1. EHLLAPI介绍

前面已经多次提到了EHLLAPI, 它是Emulator High Level Language API的简写,直译就是“仿真器高级语言接口”。 实际上,EHLLAPI是一个系列API的统称,包含3个不同的API:

  • IBM Standard HLLAPI
  • IBM Enhanced HLLAPI
  • Windows High Level Language API (WinHLLAPI)

这3个API提供的基本功能都一样,使用方法也一样,入口函数都是hllapi(参数1,参数2,参数3,参数4)。只是有些提供一些额外的功能。在大多数日常工作场景中,它们没有什么区别。不同的API对应的dll文件名不同,所以想用哪一个API就引用对应的文件名就是了。
以下是API dll文件名对照表, IBM官网上有详细介绍.
在这里插入图片描述
有意思的是,对于32-bit的Standard API和Enhanced API对应的dll文件,IBM自己的官方文档说法不一致。上图中,EHLAPI32.dll是Standard API, 而在下图中, 实验室是Enhanced API. PCSHLL32.dll正好相反。下图正确的可能性大。
在这里插入图片描述

安装完ACS的EHLLAPI增强包后,可以看到这些dll文件:
在这里插入图片描述

2.EHLLAPI的基本语法

前面介绍过了,3个EHLLAPI基本相同,所以以下示例均使用EHLAPI32.dll
因为VBScrip 不支持引入dll文件,所以以下只介绍VBA和C#, 当然C/C++和Java也是官方标准支持的。

2.1 入口函数hllapi()

EHLLAPI 用的是非常古早的接口方法,整个API就只有一个函数, 这个函数有4个参数。其中第一个参数是功能代码,剩下的3个参数和根据功能代码不同,其含义也不同。以下是几个常用功能码:

  • 连接到仿真器:1
  • 设置光标位置:40
  • 发送字符到仿真器: 3
  • 读取仿真器上指定位置的内容:8
  • 查询仿真器是否允许输入(Wait): 4
  • 配置参数设置: 9

日常用到的功能也就是这些了。想象一下用户的操作:

  • 在屏幕上输入(需要定位光标,需要确定系统可用允许输入,需要发送字符)
  • 后台系统处理输入后,会反馈显示一些信息(需要定位光标,读取指定个数的字符)

注意: hllapi()函数执行结果通常是通过第4个参数指示的,函数返回值没有意义,不应使用。

2.2 使用Excel VBA编程

再没有比Excel更顺手的编程工具了:

  • 自带UI
  • 自带数据库(工作表)
  • 无需安装任何辅助库
    而且IBM对VBA/VBScript提供了特别支持。
2.2.1 引用API dll文件
Declare Function hllapi Lib "EHLAPI32.Dll" (Func%, ByVal Buffer$, bSize%, RetC%) As Long

注意这里4个参数的类型,除了第2个为String外,其它3个是Integer, 返回值是Long。如前所述,返回值没有意义,不要使用。
参数类型一定要按照这样定义,否则大概率你会通不过。

2.2.2 封装常用的功能函数
Function SendKeys(strData$) As Integer
    Dim intPar_1%, strPar_2$, intPar_3%, intPar_4%
    intPar_1 = 3  'Send string to PS
    strPar_2 = strData
    intPar_3 = Len(strPar_2)
    intPar_4 = 0
    Call hllapi(intPar_1, strPar_2, intPar_3, intPar_4)
    SendKeys = intPar_4
End Function

Function ConnectToPS(strData$) As Integer
    Dim intPar_1%, strPar_2$, intPar_3%, intPar_4%
    intPar_1 = 1
    strPar_2 = strData
    intPar_3 = Len(strPar_2)
    intPar_4 = 0
    Call hllapi(intPar_1, strPar_2, intPar_3, intPar_4)
    ConnectToPS = intPar_4
End Function

Function DisconnectFromPS()
    Dim intPar_1%, strPar_2$, intPar_3%, intPar_4%
    intPar_1 = 2
    strPar_2 = ""
    intPar_3 = Len(strPar_2)
    intPar_4 = 0
    Call hllapi(intPar_1, strPar_2, intPar_3, intPar_4)
    DisconnectFromPS = intPar_4
End Function

Function ReadScreen(ByRef strData$, intRow%, intCol%, intLength%) As Integer
    Dim intPar_1%, strPar_2$, intPar_3%, intPar_4%
    intPar_1 = 8
    strPar_2 = String(5000, " ")
    intPar_3 = intLength 'How many characters need to read
    intPar_4 = (intRow - 1) * intScreenCol + intCol  'Position that read from
    Call hllapi(intPar_1, strPar_2, intPar_3, intPar_4)
    strData = Left(strPar_2, intLength)
    ReadScreen = intPar_4
End Function

Function SetCursorPos(intRow%, intCol%)
    Dim intPar_1%, strPar_2$, intPar_3%, intPar_4%
    intPar_1 = 40
    strPar_2 = ""
    intPar_3 = Len(strPar_2)
    intPar_4 = (intRow - 1) * intScreenCol + intCol  'Position that set to
    Call hllapi(intPar_1, strPar_2, intPar_3, intPar_4)
    SetCursorPos = intPar_4
End Function

Function GetCursorPos(ByRef intRow%, ByRef intCol%)
    Dim intPar_1%, strPar_2$, intPar_3%, intPar_4%
    intPar_1 = 7
    strPar_2 = ""
    intPar_3 = Len(strPar_2)
    intPar_4 = 0 ' (intRow - 1) * intScreenCol + intCol  'Position that set to
    Call hllapi(intPar_1, strPar_2, intPar_3, intPar_4)
    If intPar_4 = 0 Then
        intCol = intPar_3 Mod intScreenCol
        intRow = (intPar_3 - intCol) / intScreenCol + 1
    End If
    GetCursorPos = intPar_4
End Function


Function SetParameter(strData$)
    Dim intPar_1%, strPar_2$, intPar_3%, intPar_4%
    intPar_1 = 9
    strPar_2 = strData
    intPar_3 = Len(strPar_2)
    intPar_4 = 0  'Position that set to
    Call hllapi(intPar_1, strPar_2, intPar_3, intPar_4)
    SetParameter = intPar_4
End Function

Function Wait() As Integer
    Dim intPar_1%, strPar_2$, intPar_3%, intPar_4%
    intPar_1 = 4
    strPar_2 = ""
    intPar_3 = Len(strPar_2)
    intPar_4 = 0
    Call hllapi(intPar_1, strPar_2, intPar_3, intPar_4)
    Wait = intPar_4
End Function

注意这里使用了两个常量:
Const intScreenRow = 24
Const intScreenCol = 80
它指定了仿真器屏幕的尺寸大小, 常规的大小是有24行,每行有80个字符(ASCII)。虽然不太经常发生,但是有时候在仿真器上也可以设为别的尺寸,比如说25行。为简单起见,这里要求用户用标准的24 * 80屏幕。
在上面程序中读/设光标位置时,要用到这个设置来计算位置。其背后的原理是:
整个仿真器上显示的内容可以认为是一个大的字符串,第1行第1列的字符是字符串中的第一个,第2行第2列就是第81个(假定设定的是每行80列),以此类推。第r行第c列在字符串中的位置就是 (r-1) * 80 + c

2.2.3 根据实际要求进一步封装并完成最终程序

这个要根据实际情况来做,比如说,要做一个函数,用来判断仿真器是不是允许输入

Function ReadyForInput(intSec%) As Integer
    Dim intCNT%, intResult%
    
    intCNT = 0
    Do While intCNT < intSec

        intResult = Wait()
        Select Case intResult
            Case 0
                ReadyForInput = 0
                Exit Function
            Case 1, 9
                ReadyForInput = 99
                Exit Function
        End Select
        
        Application.Wait (Now + TimeValue("00:00:01"))
        intCNT = intCNT + 1
    Loop
    
    'Time expired
    ReadyForInput = 1
End Function

以下文件提供了一个实际的案例。该工具是在S2K (一款极其古早的财务软件)中做固定资产转移(从一家公司转到另一家关联公司)。整个过程涉及5屏。

Excel 示范文件下载

2.2.4 关于ACS的EHLLAPI增强包

上面的代码中是直接使用EHLLAPI 的标准dll。实际上这个增强包里有提供一些封装好的dll (bridge, 桥接API), 有趣的是封装的格式 居然还是4参数的格式。
在安装好的目录里可以看到一些*.bas文件,这些是导出的VBA模块,里面是一些如何使用这些demo。实测下来确实是可用的。可以参考这个文件

2.3 使用C#

2.3.1 引用dll文件
    public class EhllapiFunc
    {
        //You can use EHLAPI32.dll instead, there is just tiny difference.
        [DllImport(@"PCSHLL32.dll")]
        public static extern UInt32 hllapi(out UInt32 Func, StringBuilder Data, out UInt32 Length, out UInt32 RetC);
    }

注意参数类型。

2.3.2 同VBA, 对hllapi()函数功能做封装,并构建最终程序

方法与VBA类同,只是语法上略有区别而已。
实例C#代码下载

2.4 一些细节

2.4.1 关于dll文件的位置

在引用dll时,尽量不要指定具体位置,让系统会根据path参数设定自己去找,这样同一个程序,不管用户用的是i Access for Windows还是ACS, 都不影响.

2.4.2 要关注绿屏程序自身的处理方法

如前所述,绿屏程序的特点就是改写一个大字符串中的某些字符。这时一定要仔细观察主机端程序的处理规则。比如说,某个字段是输入FA#, 上一笔做完以后,如果系统自动将这个字段清空了,那RPA程序就只管输新FA#就好了。但是如果上一笔的FA#还在,那RPA程序就需要对输入的内容做下调整,要么补一些前导空格,要么补一些后导空格,根据系统规则而定。

2.4.3 仿真器功能键

通常F3是Exit (对应"@3"), F12是Cancel(对应"@c")。 在仿真器上可以自定义回车是用Ctrl健还是Enter键,但是编程时,其实不区分,都是"@E"
@ 符号在IBM 仿真器中是特殊符号,是功能键的标志。要输入一个@字符,需要用"@@"
参见官方文档中的特殊字符定义

四、使用HACL API编写RPA程序

4.1 HACL简介

HACL 是Host Access Class Library的简称,它是一个面向对象的API。与EHLLAPI用一个单一函数做入口不同, HACL用一系列的对象来处理用户功能,因此使用起来更方便。
HACL 是官方推荐使用的API,只要有可能,尽量使用它。

注意:ACS没有提供HACL API接口

HACL的官方文档

HACL的对外接口架构
在这里插入图片描述
Automation对象层次
在这里插入图片描述

基本上,使用的最多的是autECLSession对象。

4.2 用VBA编程

使用前要添加PCOMM引用。
在这里插入图片描述

官方范例

Option Explicit
Dim number_of_connections, connection_choice, input_choice
Dim autECLConnMgr As AutConnMgr
Dim autECLConnList As AutConnList
Dim autECLSession As AutSess
Sub test()
    Dim number_of_connections, connection_choice, input_choice
    Dim autECLConnMgr As AutConnMgr
    Dim autECLConnList As Object
    Dim autECLSession As AutSess
    
    autECLConnList = CreateObject("PCOMM.autECLConnList")
    autECLConnList.Refresh

    number_of_connections = autECLConnMgr.autECLConnList.Count
    If number_of_connections > 1 Then
       input_choice = InputBox("enter a connection number between 1 and " & number_of_connections)
       If input_choice = "" Then
           MsgBox ("invalid input")
       ElseIf IsNumeric(input_choice) Then
    
    '      variables used with the pcomm interface must be variants
    '      convert the connection number to an integer variant
    
           connection_choice = CInt(input_choice)
           Call display_info(connection_choice)
       Else
           MsgBox ("non numeric input" & input_choice)
       End If
    '  autECLSession.autECLXfer.SendFile "d:\pcomm\private\ad1.mac", "ad1 mac a5", "CRLF ASCII"
    ElseIf number_of_connections = 1 Then
       Call display_info(1)
    Else
       MsgBox (" no connections ")
    End If
End Sub

Sub display_info(index)
   Dim input_choice
   If (index > 0 And index <= number_of_connections) Then
      Call display_ConnList(autECLConnMgr.autECLConnList(index))
      input_choice = MsgBox("Display Session Object? ", 3)
      If input_choice = 6 Then
         Call display_Session(autECLConnMgr.autECLConnList(index).Handle)
      Else
      End If
   Else
      MsgBox ("invalid input range " & connection_choice)
   End If
End Sub

Sub display_ConnList(dis_object)
   Dim button_id
   button_id = MsgBox( _
      "Name          " & dis_object.Name & (Chr(13)) & _
      "Handle        " & dis_object.Handle & (Chr(13)) & _
      "ConnType      " & dis_object.ConnType & (Chr(13)) & _
      "CodePage      " & dis_object.CodePage & (Chr(13)) & _
      "Started       " & dis_object.Started & (Chr(13)) & _
      "CommStarted   " & dis_object.CommStarted & (Chr(13)) & _
      "APIEnabled    " & dis_object.APIEnabled & (Chr(13)) & _
      "Ready         " & dis_object.Ready, _
      0, "autECLConnMgr.autECLConnList")
End Sub

Sub display_Session(SessHandle)
   Dim button_id
    autECLSession.SetConnectionByHandle (SessHandle)
   'autECLSession.ConnectCommunication(Boolean ConnFlag)
   'autECLSession.ConnectCommunication(FALSE)
   button_id = MsgBox( _
            "Name " & autECLSession.Name & (Chr(13)) & _
            "Handle " & autECLSession.Handle & (Chr(13)) & _
            "ConnType " & autECLSession.ConnType & (Chr(13)) & _
            "CodePage " & autECLSession.CodePage & (Chr(13)) & _
            "Started " & autECLSession.Started & (Chr(13)) & _
            "CommStarted " & autECLSession.CommStarted & (Chr(13)) & _
            "APIEnabled " & autECLSession.APIEnabled & (Chr(13)) & _
            "Ready " & autECLSession.Ready, _
            0, "autECLSession")
   Call display_PS
   Call display_OIA
   Call display_Xfer
   Call display_WinMetrics
End Sub

Sub display_PS()
   Dim button_id
   button_id = MsgBox( _
        "NumRows " & autECLSession.autECLPS.NumRows & (Chr(13)) & _
        "NumCols " & autECLSession.autECLPS.NumCols & (Chr(13)) & _
        "CursorPosRow " & autECLSession.autECLPS.CursorPosRow & (Chr(13)) & _
        "CursorPosCol " & autECLSession.autECLPS.CursorPosCol & (Chr(13)) & _
        "Name " & autECLSession.autECLPS.Name & (Chr(13)) & _
        "Handle " & autECLSession.autECLPS.Handle & (Chr(13)) & _
        "ConnType " & autECLSession.autECLPS.ConnType & (Chr(13)) & _
        "CodePage " & autECLSession.autECLPS.CodePage & (Chr(13)) & _
        "Started " & autECLSession.autECLPS.Started & (Chr(13)) & _
        "CommStarted " & autECLSession.autECLPS.CommStarted & (Chr(13)) & _
        "APIEnabled " & autECLSession.autECLPS.APIEnabled & (Chr(13)) & _
        "Ready " & autECLSession.autECLPS.Ready, _
            0, "autECLSession.autECLPS")
   Call display_FieldList
End Sub

Sub display_FieldList()
   Dim button_id
   Dim field_data
   autECLSession.autECLPS.autECLFieldList.Refresh
   If autECLSession.autECLPS.autECLFieldList.Count > 0 Then
      Dim FieldText
      FieldText = autECLSession.autECLPS.autECLFieldList(1).GetText

      button_id = MsgBox( _
         "StartRow " & autECLSession.autECLPS.autECLFieldList(1).StartRow & (Chr(13)) & _
         "StartCol " & autECLSession.autECLPS.autECLFieldList(1).StartCol & (Chr(13)) & _
         "EndRow   " & autECLSession.autECLPS.autECLFieldList(1).EndRow & (Chr(13)) & _
         "EndCol   " & autECLSession.autECLPS.autECLFieldList(1).EndCol & (Chr(13)) & _
         "Length   " & autECLSession.autECLPS.autECLFieldList(1).Length & (Chr(13)) & _
         "Modified " & autECLSession.autECLPS.autECLFieldList(1).Modified & (Chr(13)) & _
         "Protected " & autECLSession.autECLPS.autECLFieldList(1).Protected & (Chr(13)) & _
         "Numeric  " & autECLSession.autECLPS.autECLFieldList(1).Numeric & (Chr(13)) & _
         "HighIntensity " & autECLSession.autECLPS.autECLFieldList(1).HighIntensity & (Chr(13)) & _
         "PenDetectable " & autECLSession.autECLPS.autECLFieldList(1).PenDetectable & (Chr(13)) & _
         "Display  " & autECLSession.autECLPS.autECLFieldList(1).Display & (Chr(13)) & _
         "text of field " & FieldText, _
            0, "autECLSession.autECLPS.autECLFieldList")
   Else
     MsgBox ("No FieldList elements to display ")
   End If
End Sub

Sub display_OIA()
   Dim button_id
   button_id = MsgBox( _
        "Alphanumeric " & autECLSession.autECLOIA.Alphanumeric & (Chr(13)) & _
        "APL          " & autECLSession.autECLOIA.APL & (Chr(13)) & _
        "Katakana     " & autECLSession.autECLOIA.Katakana & (Chr(13)) & _
        "Hiragana     " & autECLSession.autECLOIA.Hiragana & (Chr(13)) & _
        "DBCS         " & autECLSession.autECLOIA.Dbcs & (Chr(13)) & _
        "UpperShift   " & autECLSession.autECLOIA.UpperShift & (Chr(13)) & _
        "NumLock      " & autECLSession.autECLOIA.NumLock & (Chr(13)) & _
        "CapsLock     " & autECLSession.autECLOIA.CapsLock & (Chr(13)) & _
        "InsertMode   " & autECLSession.autECLOIA.InsertMode & (Chr(13)) & _
        "CommErrorReminder " & autECLSession.autECLOIA.CommErrorReminder & (Chr(13)) & _
        "MessageWaiting " & autECLSession.autECLOIA.MessageWaiting & (Chr(13)) & _
        "InputInhibited " & autECLSession.autECLOIA.InputInhibited & (Chr(13)) & _
        "Name         " & autECLSession.autECLOIA.Name & (Chr(13)) & _
        "Handle       " & autECLSession.autECLOIA.Handle & (Chr(13)) & _
        "ConnType     " & autECLSession.autECLOIA.ConnType & (Chr(13)) & _
        "CodePage     " & autECLSession.autECLOIA.CodePage & (Chr(13)) & _
        "Started      " & autECLSession.autECLOIA.Started & (Chr(13)) & _
        "CommStarted " & autECLSession.autECLOIA.CommStarted & (Chr(13)) & _
        "APIEnabled " & autECLSession.autECLOIA.APIEnabled & (Chr(13)) & _
        "Ready " & autECLSession.autECLOIA.Ready, _
            0, "autECLSession.autECLOIA")
End Sub

Sub display_Xfer()
   Dim button_id
   button_id = MsgBox( _
           "Name " & autECLSession.autECLXfer.Name & (Chr(13)) & _
           "Handle " & autECLSession.autECLXfer.Handle & (Chr(13)) & _
           "ConnType " & autECLSession.autECLXfer.ConnType & (Chr(13)) & _
           "CodePage " & autECLSession.autECLXfer.CodePage & (Chr(13)) & _
           "Started " & autECLSession.autECLXfer.Started & (Chr(13)) & _
           "CommStarted " & autECLSession.autECLXfer.CommStarted & (Chr(13)) & _
           "APIEnabled " & autECLSession.autECLXfer.APIEnabled & (Chr(13)) & _
           "Ready " & autECLSession.autECLXfer.Ready, _
            0, "autECLSession.autECLXfer")
End Sub

Sub display_WinMetrics()
   Dim button_id
   button_id = MsgBox( _
         "WindowTitle " & autECLSession.autECLWinMetrics.WindowTitle & (Chr(13)) & _
         "Xpos " & autECLSession.autECLWinMetrics.XPos & (Chr(13)) & _
         "Ypos " & autECLSession.autECLWinMetrics.YPos & (Chr(13)) & _
         "Width " & autECLSession.autECLWinMetrics.Width & (Chr(13)) & _
         "Height " & autECLSession.autECLWinMetrics.Height & (Chr(13)) & _
         "Visible " & autECLSession.autECLWinMetrics.Visible & (Chr(13)) & _
         "Active " & autECLSession.autECLWinMetrics.Active & (Chr(13)) & _
         "Minimized " & autECLSession.autECLWinMetrics.Minimized & (Chr(13)) & _
         "Maximized " & autECLSession.autECLWinMetrics.Maximized & (Chr(13)) & _
         "Restored " & autECLSession.autECLWinMetrics.Restored & (Chr(13)) & _
         "Name " & autECLSession.autECLWinMetrics.Name & (Chr(13)) & _
         "Handle " & autECLSession.autECLWinMetrics.Handle & (Chr(13)) & _
         "ConnType " & autECLSession.autECLWinMetrics.ConnType & (Chr(13)) & _
         "CodePage " & autECLSession.autECLWinMetrics.CodePage & (Chr(13)) & _
         "Started " & autECLSession.autECLWinMetrics.Started & (Chr(13)) & _
         "CommStarted " & autECLSession.autECLWinMetrics.CommStarted & (Chr(13)) & _
         "APIEnabled " & autECLSession.autECLWinMetrics.APIEnabled & (Chr(13)) & _
         "Ready " & autECLSession.autECLWinMetrics.Ready, _
            0, "autECLSession.autECLWinMetrics")
End Sub

4.3 用VBScript

方法跟VBA基本一样

sub subSub1_()
   dim  autECLSession 
   Dim ExcelApp, DataFile, DataSheet, SKU,Status, intExcelRow, intExcelCol
   set autECLSession = CreateObject("PCOMM.autECLSession")
   autECLSession.SetConnectionByName("A")
   WScript.Echo "Session hanlde: " & autECLSession.Handle
   
   Set ExcelApp = CreateObject("Excel.Application")
   ExcelApp.Visible = True
   Set  DataFile = ExcelApp.Workbooks.Open("C:\temp\Data.xlsx")
   set DataSheet = DataFile.Worksheets("Data")
   
   intExcelRow = 2
   do while trim(DataSheet.Cells(intExcelRow,3).Value) <>""
		SKU = trim(DataSheet.Cells(intExcelRow,"C").Value)
		status = trim(DataSheet.Cells(intExcelRow,"D").Value)
	   REM Start from "Define the Query" screen
	   
	   autECLSession.autECLOIA.WaitForAppAvailable
	   autECLSession.autECLOIA.WaitForInputReady
	   REM **** "Select records"
	   autECLSession.autECLPS.WaitForCursor 13,3,10000
	   autECLSession.autECLPS.SetText "1", 13, 3
	   autECLSession.autECLOIA.WaitForInputReady
	   autECLSession.autECLPS.SendKeys "[enter]"

	   REM **** Input criteria **********
	   autECLSession.autECLPS.WaitForCursor 7,10,1000
	   autECLSession.autECLOIA.WaitForAppAvailable   
	   autECLSession.autECLOIA.WaitForInputReady
	   autECLSession.autECLPS.SetText "IPROD", 7,10

	   autECLSession.autECLPS.WaitForCursor 7,28,1000
	   autECLSession.autECLOIA.WaitForAppAvailable   
	   autECLSession.autECLOIA.WaitForInputReady
	   autECLSession.autECLPS.SetText "EQ",7,28
	   
	   autECLSession.autECLPS.WaitForCursor 7,35,1000
	   autECLSession.autECLOIA.WaitForAppAvailable   
	   autECLSession.autECLOIA.WaitForInputReady
	   autECLSession.autECLPS.SetText "'" & SKU & "'",7,35
	   
	   autECLSession.autECLOIA.WaitForAppAvailable   
	   autECLSession.autECLOIA.WaitForInputReady
	   autECLSession.autECLPS.SendKeys "[enter]"   
	   
	   autECLSession.autECLOIA.WaitForAppAvailable   
	   autECLSession.autECLOIA.WaitForInputReady
	   autECLSession.autECLPS.SendKeys "[pf5]"
	   
	   autECLSession.autECLPS.Wait 1000 
	   
	   autECLSession.autECLOIA.WaitForAppAvailable   
	   autECLSession.autECLOIA.WaitForInputReady
	   autECLSession.autECLPS.SendKeys "[enter]" 
   
		intExcelRow = intExcelRow +1
   loop
   
end sub

4.4 用C#

没有实质性区别,同理,使用前添加PCOMM的引用。

4.5 ACS和PCOMM的录屏和回放功能

ACS和 都提供录屏回放功能,相当于Excel中的宏录制。
PCOMM是基于VBScript的,使用的是HACL API, 上面VBScript的代码就是在录屏的基础上改的。
ACS是基于xml形式的,还没有仔细研究。
不过通常不建议用这种方式,因为可控性太差了。


总结

基本上,掌握了以上技巧,AS400绿屏仿真器RPA就没什么问题了,剩下的只是多实践了。
遇到问题,多看官方文档,多数情况下都可以解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值