Reflection provides a number of methods you can use to navigate through IBM 3270 or 5250 screens. After sending a command (Enter, PF3, etc.) to a host, automated applications must wait until the host screen has fully arrived before attempting to send any data or commands to the host.
When developing API applications for IBM 3270 or 5250 host sessions over TCP/IP connections, it is important to be aware of the limitations of the underlying TN3270 and TN5250 protocols. In some cases, the data stream from a Host system is broken across multiple TCP/IP packets, so these packets arrive at different times. This can lead to errors in an automation application if it tries to enter data before the complete Host screen is displayed and ready for input.
Typically, this is not a problem when a user is sitting in front of the terminal session, because the few seconds it takes for the user to realize the Host screen has updated and then type the next input data is greater than the interval between the packets arriving. But an automated program typically takes just milliseconds to process the arriving data and sends the next outbound data immediately if it isn't designed to wait for the screen to update.
Reflection provides several Wait-type methods that can be called after the inbound keystrokes are sent to the Host. These methods pause execution until the new Host screen has fully arrived, and the next inbound data can be sent.
While using a Reflection Wait method is a requirement for creating reliable Host screen navigation, getting stellar performance out of screen navigation in an automation program is one of the goals of an application developer. And the type of Wait method you use can significantly impact performance.
There are a variety of Wait methods available in the Reflection Desktop API. Some are simple to use, but take longer to execute, whereas others complete quickly but require additional coding to verify the results. The WaitForHostSettle or WaitForKeyboardEnabled methods wait a set interval (settletime) after any Host session has updated, and are simple to use in your code. Unfortunately, these methods use a hard-coded timer that is not responsive to fast host connections or screen updates and can lead to very slow performance.
Other methods, such as WaitForText or WaitForCursor, can be used to verify that a specific host screen has arrived without waiting a set time. However, because the TCP/IP stack breaks large frames apart, these methods can sometimes falsely indicate that a screen is ready, when it has only partially arrived.
To provide the best solution for reliable screen navigation and performance, consider creating your own "SmartWait" method. This is what we call a method that makes calls to two or more Wait-type methods that do not rely on timers and waits until both of them indicate the screen has arrived before it indicates the screen is ready. Using just a single Wait-type function that doesn't rely on a hard-coded timer can work in many cases. But to be absolutely certain that screen-navigation is as reliable as possible, creating a function within your own code that uses a combination of these types of functions is the best means for navigation.
For example, combining the WaitForText with the WaitForCursor methods with unique screen values and making sure both have identified the appropriate text and cursor locations before proceeding in the code is a great place to start. There are many ways to structure your own SmartWait method, but here is one example that is fairly quick and efficient.
An Example of a SmartWait Method |
Copy Code
|
---|---|
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Attachmate.Reflection.Framework; using Attachmate.Reflection.Emulation.IbmHosts; using Attachmate.Reflection.UserInterface; namespace UsingSmartWait { class Program { // SmartWait is a local function used to determine if a Host screen has appeared using the WaitForText and WaitForCursor methods. // Parameters passed include: // sText String of Host data to be searched for. // sTextRow Integer of Host screen row with starting location for Host data to be searched for. // sTextColumn Integer of Host screen column with starting location for Host data to be searched for. // cRow Integer of Host screen row with location of cursor. // cColumn Integer of Host screen column with location of cursor. // screen IIbmScreen variable for the host screen object. static bool SmartWait(string sText, int sTextRow, int sTextColumn, int cRow, int cColumn, IIbmScreen screen) { int timeout; timeout = 50; // milliseconds to wait until a retry of the Reflection Wait method. bool TextPresent; TextPresent = false; // set value that searched for Text is not present yet. bool CursorPresent; CursorPresent = false; // set value that cursor location is not found yet. Attachmate.Reflection.ReturnCode returnValue; // return code from Reflection methods. DateTime StartTotalTime = DateTime.Now; // keep track of total elapsed time while searching for Host data. // enter loop to wait for Host screen to be fully updated. while (!(TextPresent && CursorPresent)) { // check to see if 20 seconds have passed, so an exit from this function can happen if the Host screen never arrives. if (((DateTime.Now - StartTotalTime).TotalMilliseconds < 20000)) { // if the Host screen text is not present then continue looking for it. if (!TextPresent) { // check to see if the Host screen text is present. if ((Convert.ToString(returnValue = screen.WaitForText(timeout, sText, sTextRow, sTextColumn, 0)) == "Success")) { TextPresent = true; // the data on the Host screen has arrived. } } // if the Host screen cursor is not present on the screen then continue looking for it. if (!CursorPresent) { // check to see if the Host screen cursor is present. if ((Convert.ToString(returnValue = screen.WaitForCursor(timeout, cRow, cColumn)) == "Success")) { CursorPresent = true; // the cursor is positioned where it is expected on the Host screen. } } } // only wait for a total of 20 seconds and then exit, since the Host screen will probably never arrive // after this point and we don't want the code to get stuck in the SmartWait() function forever. else { return false; // the Host screen which was expected never arrived. } } return true; // the Host screen with the data expected has arrived and the cursor is at the location expected. } static void Main(string[] args) { //......Code to call the SmartText method as shown below........................... } } } |
There are several things to note about this SmartWait method:
This example creates a session that connects to the Reflection demo and navigates to a screen, using the SmartWait method.
You can run this sample by copying in the code shown earlier into a project and then replacing the Main method with the content shown below.
Be sure to add references to the following assemblies before you run this sample:
using Attachmate.Reflection.Framework;
using Attachmate.Reflection.Emulation.IbmHosts;
using Attachmate.Reflection.UserInterface;
Using the SmartWait Method to Navigate |
Copy Code
|
---|---|
//............................................................................................................ //....Use the code shown above that includes the SmartWait method... //............................................................................................................ static void Main(string[] args) { // Get an instance of Reflection, create a terminal, and connect to the Reflection demo Application app = MyReflection.CreateApplication("myWorkspace", true); IIbmTerminal terminal = (IIbmTerminal)app.CreateControl(new Guid("{09E5A1B4-0BA6-4546-A27D-FE4762B7ACE1}")); terminal.HostAddress = "demo:ibm3270.sim"; terminal.Port = 623; terminal.Connect(); // Create a View to make the session visible IFrame frame = (IFrame)app.GetObject("Frame"); frame.CreateView(terminal); IIbmScreen ibmscreen = terminal.Screen; // For each screen, identify a string on the screen to search for and the initial positon of the cursor after the screen loads. // For the first screen, wait until the string "ONLINE" is found at row 1 and column 13, and the cursor location is row 20 and column 16. bool HostScreenFound = SmartWait("ONLINE", 1, 13, 20, 16, ibmscreen); // If the SmartWait method returns success (true), the appropriate Host screen was found and you can enter commands on the screen. if (HostScreenFound) { ibmscreen.SendControlKey(ControlKeyCode.Transmit); } else { Console.Write("the screen was not found."); Environment.Exit(0); } // Continue with the application... } |