如何使 SendKeys 在 IBM Host Access Library 中同步动作

2024-04-14

我用用于 COM 自动化的 IBM 主机访问类库 https://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/com.ibm.pcomm.doc/books/html/host_access08.htm?lang=en作为通过终端仿真器与 IBM AS400(又名 iSeries、IBM i、绿屏、5250)进行通信的一种方式。我注意到,当您发出“SendKeys”指令时,控制权会在 IBM 模拟器完成该命令之前返回到您的应用程序。这可能会导致计时问题,因为您可能会在系统准备好接受之前发送另一个“SendKeys”指令。

例如:

Imports AutPSTypeLibrary
Imports AutConnListTypeLibrary
Imports AutSessTypeLibrary

Sub Example
    Dim connections As New AutConnList
    connections.Refresh()
    If connections.Count < 1 Then Throw New InvalidOperationException("No AS400 screen can currently be found.")
    Dim connection As IAutConnInfo = DirectCast(connections(1), IAutConnInfo)

    _Session = New AutSess2
    _Session.SetConnectionByHandle(connection.Handle)
    Dim _Presentation As AutPS = DirectCast(_Session.autECLPS, AutPS)
    _Presentation.SendKeys("PM70[enter]", 22, 8)
    _Presentation.SendKeys("ND71221AD[enter]", 22, 20)

End Sub

在调试器中单步执行代码时可以正常工作,但在正常运行时会失败,因为第二条指令发送得太早。

解决这个问题的一种方法是在每个命令后面放置一个计时器或循环,以减慢调用程序的速度。我认为这不太理想,因为时间长度并不总是可预测的,您通常会等待比需要的时间更长的时间来适应偶尔的打嗝。这会减慢整个过程的运行时间。

解决此问题的另一种方法是等待,直到屏幕上由于发送的命令而出现可测试的条件。这有时会起作用,但某些命令不会导致屏幕更改进行测试,如果您希望将命令调用抽象到类或子例程中,则必须传递要监视的屏幕条件。

我想找到一种适用于一般情况的“等待”方法。像 autECLScreenDesc 类这样的选项似乎必须根据非常具体的条件进行定制。

autECLPS(又名 AutPS)类有许多 Wait 方法(等待,WaitForCursor,WaitWhileCursor,WaitForString,WaitWhileString,WaitForStringInRect,WaitWhileStringInRect,WaitForAttrib,WaitWhileAttrib,WaitForScreen,WaitWhileScreen)但它们似乎也在等待特定的条件,不适用于一般情况。一般情况对我来说很重要,因为我实际上正在尝试编写一个通用字段更新子例程,可以从 .dll 内部和外部的许多地方调用该子例程。

这个例子是用 VB.NET 编写的,但我希望 C#、C++、VB6、Java 也能有同样的行为;任何使用 IBM 的产品Windows 个人通信,版本 6.0 主机访问类库。 https://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/com.ibm.pcomm.doc/books/html/host_access.htm?lang=en


“操作员信息区”类似乎为这个问题提供了解决方案。

我的一般情况似乎可以正常使用此实现:

 Friend Sub PutTextWithEnter(ByVal field As FieldDefinition, ByVal value As String)
    If IsNothing(field) Then Throw New ArgumentNullException("field")
    If IsNothing(value) Then Throw New ArgumentNullException("value")
    _Presentation.SendKeys(Mid(value.Trim, 1, field.Length).PadRight(field.Length) & "[enter]", field.Row, field.Column)
    WaitForEmulator(_Session.Handle)
End Sub

Private Sub WaitForEmulator(ByVal EmulatorHandle As Integer)
    Dim Oia As New AutOIATypeLibrary.AutOIA
    Oia.SetConnectionByHandle(EmulatorHandle)
    Oia.WaitForInputReady()
    Oia.WaitForAppAvailable()
End Sub

我感谢一位名为“khieyzer”的用户这个留言板 http://www.utteraccess.com/forum/index.php?showtopic=2028886感谢您指出我们这个干净且通用的解决方案。

Edit:

经过几周的调试并解决时序和资源释放问题后,该方法现在如下所示:

Private Sub WaitForEmulator(ByRef NeededReset As Boolean)
    Dim Oia As New AutOIA
    Oia.SetConnectionByHandle(_Presentation.Handle)

    Dim inhibit As InhibitReason = Oia.InputInhibited
    If inhibit = InhibitReason.pcOtherInhibit Then
        _Presentation.SendKeys("[reset]")
        NeededReset = True
        WaitForEmulator(NeededReset)
        Marshal.ReleaseComObject(Oia)
        Exit Sub
    End If

    If Not Oia.WaitForInputReady(6000) Then
        If Oia.InputInhibited = InhibitReason.pcOtherInhibit Then
            _Presentation.SendKeys("[reset]")
            NeededReset = True
            WaitForEmulator(NeededReset)
            Marshal.ReleaseComObject(Oia)
            Exit Sub
        Else
            Marshal.ReleaseComObject(Oia)
            Throw New InvalidOperationException("The system has stopped responding.")
        End If
    End If

    Oia.WaitForInputReady()
    Oia.WaitForAppAvailable()
    Marshal.ReleaseComObject(Oia)
End Sub
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使 SendKeys 在 IBM Host Access Library 中同步动作 的相关文章

随机推荐