title: How to make SendKeys act Synchronously in IBM Host Access Library
body: <p>I use the <a href="https://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/com.ibm.pcomm.doc/books/html/host_access08.htm?lang=en" rel="nofollow noreferrer">IBM Host Access Class Library for COM Automation</a> 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.</p>
  
  <p>For example:</p>
  
  <pre><code>Imports AutPSTypeLibrary
  Imports AutConnListTypeLibrary
  Imports AutSessTypeLibrary
  
  Sub Example
      Dim connections As New AutConnList
      connections.Refresh()
      If connections.Count &lt; 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
  </code></pre>
  
  <p>would work correctly when stepping through code in a debugger, but would fail when running normally because the second instruction was sent too soon.</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>The autECLPS (aka AutPS) class has a number of Wait methods <strong>(Wait, WaitForCursor, WaitWhileCursor, WaitForString, WaitWhileString, WaitForStringInRect, WaitWhileStringInRect, WaitForAttrib,  WaitWhileAttrib, WaitForScreen, WaitWhileScreen)</strong> 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.</p>
  
  <p>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 <a href="https://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/com.ibm.pcomm.doc/books/html/host_access.htm?lang=en" rel="nofollow noreferrer">Personal Communications for Windows, Version 6.0
  Host Access Class Library.</a></p>