如何使SendKeys在IBM Host Access Library中同步动作 [英] How to make SendKeys act Synchronously in IBM Host Access Library

查看:237
本文介绍了如何使SendKeys在IBM Host Access Library中同步动作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用用于COM自动化的IBM主机访问类库,作为一种通过终端仿真器与IBM AS400(又名iSeries,IBM i,绿屏,5250)进行通信的方式.我注意到当您发出"SendKeys"指令时,在IBM仿真器完成命令之前,控制权将返回到您的应用程序.这可能会导致时序问题,因为您可能随后会在系统准备好接受它之前发送另一条"SendKeys"指令.

I use the IBM Host Access Class Library for COM Automation as a way to communicate with an IBM AS400 (aka iSeries, IBM i, green screen, 5250) through a terminal emulator. I notice that when you issue a "SendKeys" instruction, control returns to your application before the IBM emulator finishes with the command. This can lead to timing problems because you might then send another "SendKeys" instruction before the system is ready to accept it.

例如:

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

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

would work correctly when stepping through code in a debugger, but would fail when running normally because the second instruction was sent too soon.

一种使用此方法的方法是在每个命令之后放置一个计时器或循环,以降低调用程序的速度.我认为这不太理想,因为时间长度并非总是可以预测的,因此您有时会等待比必要时间更长的时间来适应偶尔的打h.这会减慢整个过程的运行时间.

One way to work with this is to put a timer or loop after each command to slow the calling program down. I consider this less than ideal because the length of time is not always predictable, you will often be waiting longer than necessary to accommodate an occasional hiccup. This slows down the run time of the entire process.

解决此问题的另一种方法是等待发送的命令导致屏幕上出现可测试的情况.有时这会起作用,但是某些命令不会导致屏幕变化的测试,如果您希望抽象化调用类或子例程的命令,则必须传递要注意的屏幕条件.

Another way to work around this is to wait until there is a testable condition on the screen as a result of your sent command. This will work sometimes, but some commands do not cause a screen change to test and if you are looking to abstract your command calling into a class or subroutine, you would have to pass in what screen condition to be watching for.

我想找到的是在一般情况下都可以使用的等待"方法之一.像autECLScreenDesc类之类的选项似乎必须针对非常特定的条件进行量身定制.

What I would like to find is one of the "Wait" methods that will work in the general case. Options like the autECLScreenDesc class seem like they have to be tailored to very specific conditions.

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

The autECLPS (aka AutPS) class has a number of Wait methods (Wait, WaitForCursor, WaitWhileCursor, WaitForString, WaitWhileString, WaitForStringInRect, WaitWhileStringInRect, WaitForAttrib, WaitWhileAttrib, WaitForScreen, WaitWhileScreen) but they also seem to be waiting for specific conditions and do not work for the general case. The general case it important to me because I am actually trying to write a general purpose field update subroutine that can be called from many places inside and outside of my .dll.

这个例子是用VB.NET编写的,但是我希望C#,C ++,VB6,Java的行为相同.使用IBM的 Windows个人通讯,版本6.0 主机访问类库.

This example is written in VB.NET, but I would expect the same behavior from C#, C++, VB6, Java; really anything that uses IBM's Personal Communications for Windows, Version 6.0 Host Access Class Library.

推荐答案

操作员信息区域"类似乎为该问题提供了解决方案.

The "Operator Information Area" class seems to provide a solution for this problem.

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

My general case seems to be working correctly with this implementation:

 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"的用户指出我们的这种干净通用的解决方案.

I give thanks to a user named "khieyzer" on this message board for pointing our this clean and general-purpose solution.

经过几周的调试并解决了计时和资源释放问题,该方法现在显示为:

After a few weeks debugging and working through timing and resource release issues, this method now reads like:

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

这篇关于如何使SendKeys在IBM Host Access Library中同步动作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆