Zum Inhalt

Beispielmakros

Die nachstehenden Beispiele eignen sich als Ausgangspunkt für die Erstellung erfolgreicher Makros, in denen die Funktionen des Makroeditors ideal genutzt werden.

Grundlegende Hostinteraktion

In diesem Beispiel wird die grundlegende Hostinteraktion dargestellt. Dazu zählen die folgenden Interaktionen:

  • Daten an den Host senden
  • Auf die Anzeige von Bildschirmen warten
  • Das yield-Schlüsselwort verwenden, um auf asynchrone Funktionen zu warten
  • Text auf dem Bildschirm lesen
  • Dem Benutzer grundlegende Informationen anzeigen
  • Fehlergrundlagen behandeln

Für alle Makros sind standardmäßig die folgenden Objekte verfügbar:

  1. session – Haupteinstiegspunkt zum Host. Kann Verbindungen herstellen und trennen und bietet Zugriff auf das PresentationSpace-Objekt.

    Das aus der Sitzung abgerufene PresentationSpace-Objekt stellt den Bildschirm dar und bietet zahlreiche allgemeine Funktionen wie das Abrufen und Einrichten der Cursorposition, das Senden von Daten an den Host und das Lesen auf dem Bildschirm.

  2. wait – Dieses Objekt bietet eine einfache Möglichkeit, auf das Auftreten der verschiedenen Hoststatus zu warten, bevor weitere Daten gesendet oder auf dem Bildschirm gelesen werden.

  3. UI – Stellt die grundlegenden Funktionen der Benutzeroberfläche bereit. Zeigt Benutzern Daten an oder fragt Informationen von Benutzern ab.

    // Neue Makrofunktion erstellen
    var macro = createMacro(function*(){
    'use strict';
    
    // Für alle Makros sind standardmäßig die folgenden Objekte verfügbar:
    // 1. session – Hauptzugriffspunkt zum Host. Kann Verbindungen herstellen und trennen und bietet Zugriff auf das PresentationSpace-Objekt.
    //    Das aus der Sitzung abgerufene PresentationSpace-Objekt stellt den Bildschirm dar und bietet zahlreiche allgemeine Funktionen wie das Abrufen und Einrichten der
    //    Cursorposition, das Senden von Daten an den Host und das Lesen auf dem Bildschirm.
    // 2. wait - Dieses Objekt bietet eine einfache Möglichkeit, auf das Auftreten der verschiedenen Hoststatus zu warten, bevor weitere Daten gesendet oder auf dem Bildschirm gelesen werden.
    // 3. ui – Stellt die grundlegenden Funktionen der Benutzeroberfläche bereit. Benutzern Daten anzeigen oder Informationen von Benutzern abfragen.
    
    // Eine Variable zum Lesen und Anzeigen von Bildschirmdaten deklarieren.
    // Es wird empfohlen, alle Variablen im oberen Bereich einer Funktion zu deklarieren.
    var numberOfAccounts = 0;
    
    // Mit dem Abrufen des PresentationSpace-Objekts beginnen, das zahlreiche gängige Bildschirmoperationen bereitstellt.
    var ps = session.getPresentationSpace();
    
    try {
        // Kann die Cursorposition einrichten und abrufen
        ps.setCursorPosition(new Position(24, 2));
    
        // Die sendKeys-Funktion zum Senden von Zeichen an den Host verwenden
        ps.sendKeys('cics');
    
        // SendKeys wird auch zum Senden von Hosttasten wie PA- und PF-Tasten verwendet.
        // Siehe "Steuertasten" in der Dokumentation für alle verfügbaren Optionen
        ps.sendKeys(ControlKey.ENTER);
    
        // Darauf warten, dass der Cursor die korrekte Position erreicht.
        // Das wait-Objekt bietet verschiedene Funktionen zum Warten auf das Eintreten bestimmter Status,
        // sodass Sie weitere Tasten senden oder Daten auf dem Bildschirm lesen können. 
        yield wait.forCursor(new Position(24, 2));
    
        // Sie können Zeichen und Steuerungstasten gemeinsam in einem sendKeys-Aufruf verwenden. 
        ps.sendKeys('data' + ControlKey.TAB + ControlKey.TAB + 'more data' + ControlKey.ENTER);
    
        // Das "yield"-Schlüsselwort muss allen "wait"- und "ui"-Funktionsaufrufen voranstehen.
        // Es weist den Browser an, die Ausführung des Makros anzuhalten, bis die
        // (asynchrone) wait-Funktion zurückgegeben wird. Informationen darüber, welche Funktionen das yield-Passwort
        // erfordern, finden Sie in der Dokumentation.
        yield wait.forCursor(new Position(10, 26));
        ps.sendKeys('accounts' + ControlKey.ENTER);
    
        // Kann auch darauf warten, dass in bestimmten Bereichen des Bildschirms Text angezeigt wird 
        yield wait.forText('ACCOUNTS', new Position(3, 36)) ;
        ps.sendKeys('1' + ControlKey.ENTER);
    
        // Alle wait-Funktionen werden unterbrochen, wenn die Kriterien nicht innerhalb einer bestimmten Zeitspanne erfüllt werden.
        // Kann mit einem optionalen Parameter in den wait-Funktionen die Wartezeit erhöhen (in Millisekunden)
        // Alle Wartezeiten werden in Millisekunden angegeben. Der Standardwert ist 10 Sekunden (10000 ms). 
        yield wait.forCursor(new Position(1, 1), 15000); 
        ps.sendKeys('A' + ControlKey.ENTER);
    
        // PS provides the getText function for reading text from the screen
        numberOfAccounts = ps.getText(new Position(12, 3), 5);
    
        // Use the ui object to display some data from the screen
        ui.message('Number of active accounts: ' + numberOfAccounts);
    
        // The try / catch allows all errors to be caught and reported in a central location
    } catch (error) {
        // Again we use the ui object to display a message that an error occurred
        yield ui.message('Error: ' + error.message);
    }
    //End Generated Macro
    });
    
    // Run the macro and return the results to the Macro Runner
    // The return statement is required as the application leverages 
    // this to know if the macro succeeded and when it is finished
    return macro();
    

Benutzerinteraktion

Dieses Beispiel zeigt, wie Benutzer mithilfe der bereitgestellten API-Methoden zur Eingabe aufgefordert oder über eine Meldung benachrichtigt werden.

var macro = createMacro(function*(){
  'use strict';

  // Das "ui"-Objekt stellt Funktionen zur Abfrage und Anzeige von Informationen bereit

  // Variablen für eine spätere Verwendung deklarieren
  var username;
  var password;
  var flavor;
  var scoops;

  //Start generiertes Makro
  var ps = session.getPresentationSpace();

  try {
    // Benutzer zur Eingabe ihres Namens auffordern und den Namen in einer Variable speichern.
    // Das 'yield'-Schlüsselwort ist zum Blockieren der Ausführung erforderlich, während auf die Benutzereingabe gewartet wird.
    username = yield ui.prompt('Geben Sie Ihren Benutzernamen ein');

    // Benutzer mit bereitgestelltem Standard zur Eingabe eines Werts auffordern.
    flavor = yield ui.prompt('Was ist Ihre Lieblingseissorte?', 'Schokolade');

    // Benutzer über die 'mask'-Option zur Eingabe persönlicher Informationen auffordern. Das Eingabefeld wird bei der Eingabe maskiert.
    // Wenn ein Parameter nicht verwendet wird, kann mit 'null‘ angegeben werden, dass er nicht verwendet werden soll.
    // Hier zeigen wir durch die Angabe, dass wir keinen Standardwert zeigen müssen.
    password = yield ui.prompt('Geben Sie Ihr Passwort ein', null, true);

    // Die Aufforderung gibt null zurück, wenn der Benutzer nicht auf die Schaltfläche 'OK' klickt, sondern auf 'Abbrechen'.
    // Eine Möglichkeit zum Behandeln dieses Falls ist das Umbrechen des Aufrufs in einem try/catch-Block.
    scoops = yield ui.prompt('Wie viele Kugeln möchten Sie?');
    if (scoops === null) {
      // Dadurch wird das Makro beendet.
      return;
      // Alternativ könnte ein Fehler ausgegeben und im nachstehenden "Catch“ erfasst werden
     }
     // Die gesammelten Werte verwenden, um das Eis zu bestellen 
    ps.sendKeys(username + ControlKey.TAB + password + ControlKey.ENTER); 
    yield wait.forCursor(new Position(5, 1)); 
    ps.sendKeys(flavor + ControlKey.TAB + scoops + ControlKey.ENTER);

     // Dem Benutzer eine Meldung anzeigen. Durch die Verwendung des 'yield'-Schlüsselworts vor dem Aufruf wird die
     // weitere Ausführung des Makros blockiert, bis der Benutzer auf die Schaltfläche 'OK' klickt.
    yield ui.message('Bestellung erfolgreich. Genießen Sie Ihr ' + scoops + ' Kugeln ' + flavor + ' Eiscreme ' + username + '!');
    } catch (error) {
     // Hier verwenden wir das ui-Objekt zum Anzeigen einer Fehlermeldung
    yield ui.message(error.message);
    }
    //Ende generiertes Makro

});

return macro();

Durchlaufen von Daten

Dieses Beispiel zeigt, wie eine beliebige Anzahl an Bildschirmen durchlaufen wird und die Daten auf den jeweiligen Bildschirmen verarbeitet werden.

// Neue Makrofunktion erstellen.
var macro = createMacro(function*(){
  'use strict';

  // Variable(n) für eine spätere Verwendung erstellen var password;
  var accountNumber;
  var transactionCount = 0;
  var row = 0;

  // Eine Referenz zum PresentationSpace-Objekt abrufen.
  var ps = session.getPresentationSpace();

  try {
    // Für die Anmeldung bei der Anwendung Benutzername und Passwort eingeben. 
    yield wait.forCursor(new Position(19, 48)); 
    ps.sendKeys('bjones' + ControlKey.TAB);

    yield wait.forCursor(new Position(20, 48));
    password = yield ui.prompt('Password:', null, true); 
    ps.sendKeys(password); 
    ps.sendKeys(ControlKey.ENTER);

    // Anwendungsbefehl eingeben. 
    yield wait.forCursor(new Position(20, 38)); 
    ps.sendKeys('4'); 
    ps.sendKeys(ControlKey.ENTER);

    // Transaktionen für ein Konto werden aufgelistet. 
    yield wait.forCursor(new Position(13, 25)); 
    ps.sendKeys('2');
    // Kontonummer eingeben. Hier zur Erleichterung hartcodiert. 
    yield wait.forCursor(new Position(15, 25));
    accountNumber = yield ui.prompt('Kontonummer:', '167439459'); 
    ps.sendKeys(accountNumber); 
    ps.sendKeys(ControlKey.ENTER);

    // Warten, bis auf dem Kontoprofilbildschirm vorhanden 
    yield wait.forText('ACCOUNT PROFILE', new Position(3, 33));

    // Nach Text suchen, der anzeigt, dass die letzte Seite des Datensatzes erreicht wurde
    while (ps.getText(new Position(22, 12), 9) !== 'LAST PAGE') {

      // Während die letzte Seite mit Datensätzen nicht erreicht wurde, zur nächsten Seite mit Datensätzen wechseln. 
      ps.sendKeys(ControlKey.PF2); 
      yield wait.forCursor(new Position(1, 1));

      // Wenn die Cursorposition nicht zwischen Datensatzbildschirmen wechselt und der Bildschirm keinen Text enthält,
      // können Sie prüfen, ob ein Bildschirm aktualisiert wurde. Sie können eine
      // festgelegte Zeitspanne warten, bis eine aid-Taste für den Aufbau des Bildschirms gesendet wird.
      // Zum Beispiel:
      // yield wait.forFixedTime(1000);

      // Für alle Zeilen die Zählvariable erhöhen, wenn sie Daten enthalten.
      for (row = 5; row <= 21; row++) {

        // Es befinden sich zwei Spalten auf dem Bildschirm. Daten in Spalte 1 prüfen.
        // In diesem Beispiel wissen wir: Wenn sich an einer bestimmten
        // Position ein Leerzeichen befindet, liegt eine Transaktion vor.
        if (ps.getText(new Position(row, 8), 1) !== ' ') {
          transactionCount++;
        }
        // Daten in Spalte 2 prüfen.
        if (ps.getText(new Position(row, 49), 1) !== ' ') {
          transactionCount++;
        }
      }
    }

    // Nach dem Durchlaufen aller Datensatzseiten die Anzahl der Datensätze in einem Meldefenster anzeigen.
    yield ui.message('Es wurden ' + transactionCount + ' für Ihre Konto ' + accountNumber + ' gefunden.');

    // Log out of the application
    ps.sendKeys(ControlKey.PF13);
    ps.sendKeys(ControlKey.PF12);

    // The try / catch allows all errors to be caught and reported in a central location
  } catch (error) {
    // Here we use the ui object to display a message that an error occurred
    yield ui.message(error.message);
  } 
});  

// Here we run the macro and return the results to the Macro Runner
// The return statement is required as the application leverages 
// this to know if the macro succeeded
return macro();

Aufrufen eines Webdienstes

Dieses Beispiel zeigt, wie direkt über ein Makro ein AJAX / REST-Aufruf an einen Webdienst ausgeführt wird. Sie können Daten über Ihre Hostanwendung in den Aufruf des Webdienstes oder umgekehrt über den Webdienst in Ihre Hostanwendung integrieren.

In diesem Beispiel wird der 'Verastream Host Integrator (VHI) CICSAcctsDemo REST'-Dienst aufgerufen. Sie können den Code natürlich auch problemlos anpassen und einen anderen Webdienst aufrufen. Sie sind nicht an den VHI-Dienst gebunden.

In diesem Beispiel wird der Aufruf über einen im Sitzungsserver konfigurierten Proxy durchgeführt (wie unten beschrieben), um „Same-Origin-Policy“-Komplikationen zu vermeiden. Wenn Sie einen Webdienst verwenden, der Cross-Origin Resource Sharing (CORS) unterstützt, und wenn Sie einen modernen Browser verwenden, ist der Proxy nicht erforderlich.

Die jQuery-Bibliothek ist in Makros verfügbar. Sie können zum Aufrufen von REST-Diensten also direkt die $.post()-Funktion verwenden.

In dem Beispiel wird außerdem beschrieben, wie ein jQuery REST-Aufruf in einem neuen Promise-Muster umbrochen wird. Das über die nachstehende benutzerdefinierte Funktion zurückgegebene promise-Muster ermöglicht die Verwendung von „yield“ im Hauptmakrocode. Dadurch kann die Hauptmakroausführung warten, bis der Dienstaufruf abgeschlossen ist, bevor sie fortgesetzt wird.

 var macro = createMacro(function*() {
  'use strict';

  // Einige Variablen für eine spätere Verwendung erstellen;
  var username;
  var password;
  var accountNumber;
  var accountDetails;

  // Eine Funktion erstellen, die einen AJAX / REST-Aufruf an einen VHI-Webdienst ausführt.
  // Kann für den Aufruf eines beliebigen Webdienstes (nicht nur VHI) angepasst werden.
  // Wenn nicht CORS verwendet wird, muss die Anforderung wahrscheinlich einen
  // Proxy auf dem Sitzungsserver durchlaufen. Siehe Beispielhinweise für weitere Informationen.
  /**
   * Hartcodierte Unterstützungsfunktion zum Einschließen von AJAX / REST-Parametern, zum Aktivieren des
   * REST-Dienstes und zum Zurückgeben der Ergebnisse in einem Promise-Objekt.
   * @param {Number} Kontonummer zum Senden an die REST-Abfrage.
   * @param {String} Benutzername für den Zugriff auf den REST-Dienst.
   * @param {String} Passwort für den Zugriff auf den REST-Service.
   * @return {Promise} enthält $.post()-Ergebnisse, die mit yield kompatibel sind. 
  */
  var getAccountDetails = function (acctNum, username, password) {
    var url = "proxy1/model/CICSAcctsDemo/GetAccountDetail";
    var args = {"filters": {"AcctNum": acctNum}, "envVars": {"Username": username, "Password": password}};

    // jQuery AJAX / HTTP POST-Aufruf in einem neuen Promise-Objekt umbrechen.
    // Das hier zurückgegebene Promise-Objekt ermöglicht dem Makro über yield / wait
    // auf seinen Abschluss zu warten.
    return Promise.resolve($.post(url, JSON.stringify(args)))
      .catch(function (error) {
      // Fehler zuordnen, die im jQuery-Aufruf an unser Promise-Objekt auftreten.
      throw new Error('REST API Error: ' + error.statusText);
    });
  };

  // Start generiertes Makro
  var ps = session.getPresentationSpace();
  try {
    // Konnte hier mit dem Host interagieren, sich bei einer Hostanwendung anmelden usw.
    // Benutzername und Passwort erfassen
    username = yield ui.prompt('Username:');
    password = yield ui.prompt('Passwort:', null, true);
    accountNumber = yield ui.prompt('Kontonummer:');
    if (!username || !password || !accountNumber) {
      throw new Error('Kein Benutzername oder Passwort angegeben');
    }

    // Externen REST-Dienst aktivieren, und yields / wartet auf den Abschluss des Aufrufs.
    accountDetails = yield getAccountDetails(accountNumber, username, password);

    // Jetzt haben wir die Daten von unserem externen Dienst.
    // Können die Daten in unsere lokale Hostanwendung integrieren oder die Daten einfach dem Benutzer anzeigen.
    // In diesem Beispiel zeigen wir einfach die sich ergebenden Kontodetails an.
    if (accountDetails.result && accountDetails.result.length > 0) {
      yield ui.message(accountDetails.result[0].FirstName + ' $' + accountDetails.result[0].AcctBalance);
    } else {
      yield ui.message('Kein Datensatz für folgendes Konto gefunden: ' + accountNumber);
    }
  } catch (error) {
    // Wenn während des AJAX / REST-Aufrufs
    // oder beim Erfassen von Benutzername/Passwort ein Fehler auftritt, befinden wir uns hier.
    yield ui.message(error.message);
  }
  });

// Unser Makro ausführen
return macro();

Proxy-Unterstützung für die Skripterstellung aus verschiedenen Ursprüngen

Bei Webdiensten, die CORS nicht unterstützen, treten bei AJAX/REST-Aufrufen Fehler auf, wenn sie versuchen, auf einen nicht aus der Host Access for the Cloud-Anwendung stammenden Server zuzugreifen. Dabei handelt es sich um eine Browser-Sicherheitsfunktion.

Der Host Access for the Cloud-Server bietet eine Möglichkeit, explizit einen Proxy zu verbürgten Remoteservern bereitzustellen.

  • Öffnen Sie ..\<Installationsverzeichnis>\sessionserver\microservice\sessionserver\service.yml zur Bearbeitung.

  • Fügen Sie im Abschnitt env Folgendes hinzu:

    name: zfe.proxy.mappings
    value: proxy-path=proxy-to-address
    

    Dabei bezieht sich proxy-path auf die gewünschte URL-Zuordnung und proxy-to-address auf die URL, bei der der Aufruf über einen Proxy gesendet wird.

  • In diesem Beispiel:

    name: zfe.proxy.mappings
    value: proxy1=http://remote-vhi-server:9680/vhi-rs/
    

    Aufrufe für <Server:Port>/proxy1 werden über einen Proxy an http://remote-vhi-server:9680/vhi-rs/ gesendet.

  • Mehrere Proxyzuordnungen können angegeben werden, indem die einzelnen Zuordnungen durch ein Komma getrennt werden.

  • Bitte beachten Sie: Ein REST-Server unterstützt zwar CORS-Titel, ältere Browser tun dies jedoch nicht. Daher kann dieses Beispiel weiterhin relevant sein.

Tipp

Die Datei service.yml kann ersetzt werden, wenn Sie Host Access for the Cloud neu bereitstellen. Denken Sie daran, immer Ihre Dateien zu sichern.

Arbeiten mit Datenzellen und Attributen

Dieses Makro veranschaulicht, wie Sie Datenzellen und Attributsätze zum Überprüfen einer bestimmten Zeile/Spalte auf dem Bildschirm für Text und Attribute verwenden können. In diesem Beispiel sehen Sie Folgendes:

  • Wie Sie eine Sammlung von DataCells-Objekten für eine bestimmte Position und Länge abrufen.

  • Wie Sie DataCells-Objekte zum Erstellen einer Textzeichenfolge durchlaufen.

  • Wie Sie zum Vergleich in ähnlicher Weise auch getText() verwenden können.

  • Wie Sie mit Attributen arbeiten, eine Auflistung mit Zeichenfolgen abrufen oder feststellen, ob bestimmte Attribute an einer festgelegten Bildschirmposition angegeben sind.

var macro = createMacro(function*() {
    'use strict';

    // Präsentationsbereich für die Interaktion mit dem Host abrufen
    var ps = session.getPresentationSpace();

    // Variablen für eine spätere Verwendung deklarieren
    var cells;
    var text;
    var attrs;

    // Standardwartezeit für "wait"-Funktionen festlegen
    wait.setDefaultTimeout(10000);

    // Beispielmakro für das Arbeiten mit Datenzellen und Attributen
    try { 
        yield wait.forCursor(new Position(24, 2));

        // Datenzellen aus dem Präsentationsbereich abrufen
        // Zeile 19, Spalte 3 ist die Eingabeaufforderung 35 Zeichen lang
        // "Wählen Sie einen der folgenden Befehle:"
        cells = ps.getDataCells({row:19, col:3}, 35);
        text = '';

        // Sie können Text mithilfe von 'getText' anzeigen
        yield ui.message("Screen text: " + ps.getText({row:19, col:3}, 35));

        // Oder den Text aus den Datenzellen an den einzelnen Positionen bilden
        for(var index = 0; index < cells.length; index++) {
            text = text.concat(cells[index].getChar());
        }
        // Und den Text anzeigen
        yield ui.message("Cells text: " + text);

        // Attribute für die erste Datenzelle abrufen (cell[0])
        attrs = cells[0].getAttributes();

        // Anzeigen, ob Attribute für die Datenzelle vorhanden sind
        yield ui.message("Attribute set is empty: " + attrs.isEmpty());

        // Anzeigen, wie viele Attribute angegeben sind
        yield ui.message("Number of attributes: " + attrs.size());

        // Anzeigen, welche Attribute angegeben sind
        yield ui.message("Attributes: " + attrs.toString());

        // Anzeigen, ob das das Attribut 'HIGH_INTENSITY' angegeben ist
        yield ui.message("Is high intensity: " +
                         attrs.contains(Attribute.HIGH_INTENSITY));

        // Anzeigen, ob das Attribut 'UNDERLINE' angegeben ist
        yield ui.message("Is underline: " +
                         attrs.contains(Attribute.UNDERLINE));

        // Anzeigen, ob die Attribute 'ALPHA_NUMERIC', 'HIGH_INTENSITY' und 'PEN_DETECTABLE' angegeben sind
        yield ui.message("Is alphanumeric, intensified and pen-detectable: " +
                         attrs.containsAll([Attribute.ALPHA_NUMERIC, Attribute.HIGH_INTENSITY, Attribute.PEN_DETECTABLE]));

        // Anzeigen, ob die Attribute 'UNDERLINE', 'HIGH_INTENSITY' und 'PEN_DETECTABLE' angegeben sind
        yield ui.message("Is underline, intensified and pen-detectable: " +
                         attrs.containsAll([Attribute.UNDERLINE, Attribute.HIGH_INTENSITY, Attribute.PEN_DETECTABLE]));
    } catch (error) {
        yield ui.message(error);
    }
 //Generiertes Makro beenden
});

// Zurückgegebenes Makro ausführen
return macro();

Verwenden von Feldern und Feldlisten

Dieses Makrobeispiel veranschaulicht die Verwendung allgemeiner Funktionen für die Interaktion mit den Feldern in der Makro-API. Es wird beispielsweise dargestellt, wie Feldtext abgerufen wird, Feldinformationen angezeigt werden und wie field.setText als Alternative zu sendKeys für die Interaktion mit dem Host verwendet werden kann.

Hinweis

Aufgrund bestimmter Browseraspekte reduziert ui.message mehrere aufeinander folgende Leerzeichen zu einem einzelnen Leerzeichen. Die Leerzeichen werden im JavaScript-Code beibehalten.

var macro = createMacro(function*() {
    'use strict';

    // Präsentationsbereich für die Interaktion mit dem Host abrufen
    var ps = session.getPresentationSpace();

    // Variablen für eine spätere Verwendung deklarieren
    var fields;
    var field;
    var searchString = 'z/VM';

    // Standardwartezeit für "wait"-Funktionen festlegen
    wait.setDefaultTimeout(10000);

    // Beispielmakro für das Arbeiten mit Feldlisten und Feldern
    try { 
        yield wait.forCursor(new Position(24, 2));

        // Feldliste abrufen.
        fields = ps.getFields();

        // Die gesamte Feldliste durchlaufen und Feldinfo anzeigen.
        for(var index = 0; index < fields.size(); index++) {
            field = fields.get(index);

            yield ui.message("Field " + index + " info: " + field.toString());
        }

        yield ui.message("Hier ein Feld mit dem Text '" + searchString + "'");
        field = fields.findField(new Position(1, 1), searchString);

        if(field !== null) {
            yield ui.message("Found field info: " + field.toString());
            yield ui.message("Found field foreground is green? " + (Color.GREEN === field.getForegroundColor()));
            yield ui.message("Found field background is default? " + (Color.BLANK_UNSPECIFIED === field.getBackgroundColor()));
        }

        // Jetzt nach einem Befehlsfeld suchen und es ändern.
        field = fields.findField(new Position(23, 80));
        if(field !== null) {
            field.setText("cics");
        }

        yield ui.message("Klicken Sie mit der Maus, um 'cics' an den Host zu senden."); 
        ps.sendKeys(ControlKey.ENTER);

        // Auf neuen Bildschirm warten; neue Felder abrufen. 
        yield wait.forCursor(new Position(10, 26));
        fields = ps.getFields();

        // Benutzerfeld suchen und festlegen.
        field = fields.findField(new Position(10, 24));        
        if(field !== null) {        
            field.setText("myusername");
        }
        // Passwortfeld suchen und festlegen.
        field = fields.findField(new Position(11, 24));
        if(field !== null) {        
            field.setText("mypassword");        
        }

        yield ui.message("Click to send login to host."); 
        ps.sendKeys(ControlKey.ENTER);

        // Auf neuen Bildschirm warten; neue Felder abrufen. 
        yield wait.forCursor(new Position(1, 1));
        fields = ps.getFields();

        // Befehlsfeld suchen und 'logoff'-Befehl festlegen.
        field = fields.findField(new Position(24, 45));
        if(field !== null) {        
            field.setText("cesf logoff");
        }

        yield ui.message("Click to send logoff to host.");
        ps.sendKeys(ControlKey.ENTER);

    } catch (error) {
        yield ui.message(error);
    }
    //Ende generiertes Makro

});

// Makro ausführen
return macro();

Makro für die automatische Anmeldung für Mainframes

In diesem Beispiel wird mit dem AutoSignon-Objekt ein Makro erstellt, das die einem Benutzer zugeordneten Berechtigungsnachweise verwendet, um ein Weiterleitungsticket vom Digital Certificate Access Server (DCAS) abzurufen.

var macro = createMacro(function*() {
    'use strict';

    // Präsentationsbereich für die Interaktion mit dem Host abrufen
    var ps = session.getPresentationSpace();

    // Variable für Weiterleitungsticket für die Anmeldung
    var passTicket;

    // Anwendungs-ID für die Anmeldung
    var appId = 'CICSV41A';

    // Standardwartezeit für "wait"-Funktionen festlegen
    wait.setDefaultTimeout(10000);

    // Start generiertes Makro
    try { 
    yield wait.forCursor(new Position(24, 2));

       // Weiterleitungsticket von DCAS abrufen.
       passTicket = yield autoSignon.getPassTicket(appId);

        ps.sendKeys('cics');
        ps.sendKeys(ControlKey.ENTER);

        yield wait.forCursor(new Position(10, 26));

        // Generierten Benutzernamen mit 'sendUserName(passTicket) ...' ersetzen
        yield autoSignon.sendUserName(passTicket);

        // ps.sendKeys('bvtst01' + ControlKey.TAB + ControlKey.TAB); 
        ps.sendKeys(ControlKey.TAB + ControlKey.TAB);

        yield wait.forCursor(new Position(11, 26));

        // Generiertes Passwort mit 'sendPassword(passTicket) ...' ersetzen
        yield autoSignon.sendPassword(passTicket);

        // var userInput3 = yield ui.prompt('Passwort:', '', true);
         // if (userInput3 === null) {
             // throw new Error('Kein Passwort angegeben');
        // }
        // ps.sendKeys(userInput3);
        ps.sendKeys(ControlKey.ENTER);

        yield wait.forCursor(new Position(1, 1));
        yield ui.message('Angemeldet. Melde mich ab.'); 
        ps.sendKeys('cesf logoff'); 
        ps.sendKeys(ControlKey.ENTER);
    } catch (error) {
        yield ui.message(error);
    }
    //Ende generiertes Makro
});

// Makro ausführen
return macro();

Verwenden der Dateiübertragung (IND$File)

Mit den folgenden Beispielmakros wird veranschaulicht, wie Sie mithilfe der Dateiübertragungs-API eine Dateiliste abrufen, eine Datei herunterladen und eine Datei auf einen 3270-Host hochladen können.

Hinweis

Zum Ausführen dieser Makros müssen Sie angemeldet sein und eine Eingabeaufforderung geöffnet haben.


Makro zum Auflisten von Dateien

Mit diesem Makro wird veranschaulicht, wie Sie mithilfe der Dateiübertragungs-API mittels IND$File-Übertragung eine Dateiliste auf einem 3270-Host abrufen. Das IND$File-Übertragungsobjekt wird aus der Dateiübertragungsfactory abgerufen und dann zum Abrufen eines Arrays von HostFile-Objekten von TSO oder CMS verwendet.

var macro = createMacro(function*() {
    'use strict';

    try {
        var fileTransfer = fileTransferFactory.getInd$File();
        var hostFiles = yield fileTransfer.getHostFileListing();

        yield ui.message('Found ' + hostFiles.length + ' files');
        if (hostFiles.length > 0) {
            var firstFile = hostFiles[0];
            var msg1 = 'Der Katalogname lautet ' + firstFile.getParent() + '. ';
            var msg2 = 'The first file is ' + firstFile.getName();
            yield ui.message(msg1 + msg2);
        }
    } catch (error) {
        yield ui.message(error);
    }
});

// Makro ausführen
return macro();

Makro zum Herunterladen einer Datei

Mit diesem Makro wird veranschaulicht, wie Sie mithilfe der Dateiübertragungs-API mittels IND$File-Übertragung eine Datei von einem 3270-Host herunterladen. Das IND$File-Übertragungsobjekt wird aus der Dateiübertragungsfactory abgerufen. In diesem Beispiel ist ASCII als Übertragungsmethode festgelegt, um die Verwendung der setTransferOptions-Funktion zu veranschaulichen.

Das Beispielmakro lädt die erste Datei herunter, die von einem Aufruf an getHostFileListing zurückgegeben wurde, indem ein Download-URI mit einem Aufruf der getDownloadUrl-Funktion erstellt wird. Das Makro kann entweder in einer CMS- oder TSO-Umgebung verwendet werden, aber die Auswahl muss in der ersten Zeile angegeben oder der Code für das beabsichtigte System leicht geändert werden.

var hostEnvironment = 'CMS';  // 'TSO'
// Dateipfad erstellen, d. h. catalog/file.name oder catalog/partition/file
function getPath (fileNode) {
    var prefix = fileNode.getParent() ? fileNode.getParent() + '/' : '';
    return prefix + fileNode.getName();
}

var macro = createMacro(function*() {
    'use strict';

    try {
        var fileTransfer = fileTransferFactory.getInd$File();

        // transferMethod-Optionen sind 'binary' und 'ascii'
        fileTransfer.setTransferOptions({transferMethod: 'ascii'});

        // In dieser Demo wird die erste Datei abgerufen, die in der Liste
        var hostFiles = yield fileTransfer.getHostFileListing();
        var firstHostFile = hostFiles[0];

        if (hostEnvironment === 'CMS') { 
           yield wait.forText('Ready', new Position(1,1), 5000);
        }

        // Download
        // Wenn Ihnen der Pfad der gewünschten Datei bereits bekannt ist, übergeben Sie ihn einfach an getDownloadURL()
        var downloadUrl = fileTransfer.getDownloadURL(getPath(firstHostFile));

        // Dadurch wird der Browserspeicherort geändert. Möglicherweise ergeben sich unterschiedliche Ergebnisse in unterschiedlichen Browsern.
        window.location = downloadUrl;

        // Wenn Sie die Dateiinhalte in eine Variable einlesen möchten, anstatt sie
        // herunterzuladen, können Sie Folgendes verwenden: jQuery
        // var fileContents = yield $.get(downloadUrl);

    } catch (error) {
         yield ui.message(error);
    }
    });

// Makro ausführen
return macro();

Makro zum Hochladen einer Datei

Mit diesem Makro wird veranschaulicht, wie Sie mithilfe der Dateiübertragungs-API mittels IND$File-Übertragung eine Datei auf einen 3270-Host hochladen. Mit dem Beispielmakro wird der Benutzer aufgefordert, eine Datei im lokalen Dateisystem auszuwählen, indem das Dialogfeld des Browsers zur Dateiauswahl ausgelöst wird. Dann wird durch Aufrufen von getHostFileListing der aktuelle Katalog auf TSO oder die Laufwerkskennung auf CMS abgerufen. Schließlich wird die sendFile-Funktion aufgerufen, um die ausgewählte lokale Datei an den Host zu übermitteln.

Das Makro kann entweder in einer CMS- oder TSO-Umgebung verwendet werden, aber die Auswahl sollte in der ersten Zeile angegeben werden. In diesem Beispiel ist die Übertragungsart auf ascii festgelegt. Sie können dies jedoch in binary ändern.

var hostEnvironment = 'CMS';  // 'TSO'
 // Dialogfeld des Browsers zur Dateiauswahl programmgesteuert öffnen
function promptForFileToUpload () {
    return new Promise(function (resolve, reject) {
        // Es erfolgt keine Benachrichtigung, wenn der Benutzer das Dialogfeld zur Dateiauswahl schließt, daher nach 30 Sekunden ablehnen
        var timerId = setTimeout(reject.bind(null, 'Timed out waiting for file selection'), 30000);
        var fileSelector = document.createElement('input');
        fileSelector.setAttribute('type', 'file');
        fileSelector.onchange = function (evt) {
            var file = evt.target.files[0];
            clearTimeout(timerId);
            resolve(file);
        };
        fileSelector.click();
    });
}

var macro = createMacro(function*() {
    'use strict';

    try {
        var fileTransfer = fileTransferFactory.getInd$File();

       // transferMethod-Optionen sind 'binary' und 'ascii'
        fileTransfer.setTransferOptions({transferMethod: 'ascii'});

        var localFile = yield promptForFileToUpload();

        // Aktuellen Katalognamen abrufen und ausgewählten Dateinamen an ihn anfügen
        var hostFiles = yield fileTransfer.getHostFileListing();
        var destination = hostFiles[0].getParent() + '/' + localFile.name;

        if (hostEnvironment === 'CMS') {
           yield wait.forText('Ready', new Position(1,1), 5000);
        }

        var result = yield fileTransfer.sendFile(localFile, destination);

    } catch (error) {
        yield ui.message(error);
    }
});

 // Makro ausführen
return macro();