如何使SendKeys在IBM主机访问库中同步行动



我使用COM自动化的IBM主机访问类库作为通过终端模拟器与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)类有许多等待方法(等待,WaitForCursor, WaitWhileCursor, WaitForString, WaitWhileString, WaitForStringInRect, WaitWhileStringInRect, WaitForAttrib, waitwhiletrib, WaitForScreen, WaitWhileScreen)但它们似乎也在等待特定的条件,不适用于一般情况。一般情况下,它对我很重要,因为我实际上是试图写一个通用的字段更新子程序,可以从我的。dll内外的许多地方调用。

这个例子是用VB编写的。. NET,但我希望c#, c++, VB6, Java;任何使用IBM Windows 6.0版个人通讯系统的东西主机访问类库。

"Operator Information Area"类似乎为这个问题提供了一个解决方案。

我的一般情况下,这个实现似乎是正确的:

 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的用户,他为我们指出了这个简洁而通用的解决方案。

编辑:

经过几周的调试和处理时间和资源释放问题后,这个方法现在读起来像:

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

相关内容

  • 没有找到相关文章

最新更新