Aller au contenu

Exemples de macros

Pour vous aider à créer des macros qui tirent parti de toutes les fonctionnalités de l'éditeur de macros, les exemples ci-après sont disponibles comme point de départ.

Interactions de base avec l'hôte

Cet exemple illustre les interactions de base avec l'hôte, notamment :

  • Envoi de données à l'hôte
  • Attente de l'affichage d'écrans
  • Utilisation du mot-clé yield pour attendre des fonctions asynchrones
  • Lecture de texte à l'écran
  • Affichage d'informations de base pour l'utilisateur
  • Notions de base en matière de gestion des erreurs

Les objets suivants sont disponibles par défaut pour toutes les macros :

  1. session : point d'entrée principal pour accéder à l'hôte. Il permet de se connecter, de se déconnecter et d'accéder à l'objet PresentationSpace.

    L'objet PresentationSpace obtenu à partir de la session représente l'écran et offre de nombreuses fonctionnalités courantes telles que l'obtention et la définition de l'emplacement du curseur, l'envoi de données à l'hôte et la lecture à partir de l'écran.

  2. wait : permet simplement d'attendre que plusieurs états d'hôte se produisent avant de continuer à envoyer davantage de données ou à lire à partir de l'écran.

  3. UI : offre des fonctionnalités d'interface utilisateur de base. Il permet d'afficher des données à l'utilisateur ou de lui demander de fournir des informations.

 // Créer une fonction de macro
 var macro = createMacro(function*(){
 'use strict';

 // Les objets suivants sont disponibles par défaut pour toutes les macros :
 // 1. session : point d'entrée principal pour accéder à l'hôte. Il permet de se connecter, de se déconnecter et d'accéder à l'objet PresentationSpace.
 // L'objet PresentationSpace obtenu à partir de la session représente l'écran et offre de nombreuses fonctionnalités courantes telles que l'obtention et la définition de
 // l'emplacement du curseur, l'envoi de données à l'hôte et la lecture à partir de l'écran.
 // 2. wait : permet simplement d'attendre que plusieurs états d'hôte se produisent avant de continuer à envoyer davantage de données ou à lire à partir de l'écran.
 // 3. ui : offre des fonctionnalités d'interface utilisateur de base. Il permet d'afficher des données à l'utilisateur ou de lui demander de fournir des informations.

 // Déclarer une variable pour lire et afficher des données d'écran.
 // Comme meilleure pratique, toutes les variables doivent être déclarées au début d'une fonction.
 var numberOfAccounts = 0;

 // Commencer par obtenir l'objet PresentationSpace, qui fournit de nombreuses opérations d'écran courantes.
 var ps = session.getPresentationSpace();

 try {
     // Permet de définir et d'obtenir l'emplacement du curseur.
     ps.setCursorPosition(new Position(24, 2));

     // Utiliser la fonction sendKeys pour envoyer des caractères à l'hôte.
     ps.sendKeys('cics');

     // La fonction SendKeys est également utilisée pour envoyer des touches d'hôte telles que les touches PA et PF.
     // Se reporter à la section sur les touches de contrôle dans la documentation pour connaître toutes les options disponibles.
     ps.sendKeys(ControlKey.ENTER);

     // Attendre que le curseur soit à la position correcte.
     // L'objet wait fournit diverses fonctions pour attendre que certains états se produisent
     // afin de pouvoir continuer à envoyer d'autres touches ou à lire des données de l'écran.
     yield wait.forCursor(new Position(24, 2));

     // Vous pouvez mélanger des caractères et des touches de contrôle dans un seul appel sendKeys.
     ps.sendKeys('data' + ControlKey.TAB + ControlKey.TAB + 'more data' + ControlKey.ENTER);

     // Le mot-clé "yield" doit être utilisé devant les appels de fonction "wait" et "ui".
     // Il indique au navigateur de suspendre l'exécution de la macro jusqu'au retour
     // de la fonction wait (asynchrone). Se reporter à la documentation pour connaître les fonctions
     // qui nécessitent le mot-clé yield.
     yield wait.forCursor(new Position(10, 26));
     ps.sendKeys('accounts' + ControlKey.ENTER);

     // Possibilité d'attendre que du texte s'affiche dans certaines zones de l'écran.
     yield wait.forText('ACCOUNTS', new Position(3, 36)) ;
     ps.sendKeys('1' + ControlKey.ENTER);

     // Toutes les fonctions wait subissent un timeout si les critères ne sont pas respectés dans un délai.
     // Possibilité d'augmenter le timeout avec un paramètre facultatif dans les fonctions wait (en millisecondes).
     // Tous les timeouts sont spécifiés en millisecondes et leur valeur par défaut est de 10 secondes (10 000 ms).
     yield wait.forCursor(new Position(1, 1), 15000);
     ps.sendKeys('A' + ControlKey.ENTER);

     // PS fournit la fonction getText pour lire du texte sur l'écran.
     numberOfAccounts = ps.getText(new Position(12, 3), 5);

     // Utiliser l'objet ui pour afficher certaines données de l'écran.
     ui.message('Nombre de comptes actifs : ' + numberOfAccounts);

     // L'instruction try/catch permet de capturer toutes les erreurs et de les signaler à un emplacement centralisé.
 } catch (error) {
     // Nous utilisons à nouveau l'objet ui pour afficher un message signalant qu'une erreur s'est produite.
     yield ui.message('Error: ' + error.message);
 }
 // Fin de la macro générée
 });

 // Exécuter la macro et renvoyer les résultats dans l'outil d'exécution de macro.
 // L'instruction return est requise, car l'application s'en sert 
 // pour déterminer si la macro a réussi et le moment de fin de son exécution.
 return macro();

Interaction avec l'utilisateur

Cet exemple illustre comment utiliser les méthodes de l'API fournies pour demander à l'utilisateur de saisir des données ou lui envoyer un message.

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

  // L'objet "ui" fournit des fonctions pour inviter l'utilisateur à fournir des informations et pour afficher des informations.

  // Déclarer des variables pour une utilisation ultérieure.
  var username;
  var password;
  var flavor;
  var scoops;

  // Début de la macro générée
  var ps = session.getPresentationSpace();

  try {
    // Inviter l'utilisateur à entrer son nom et stockez-le dans une variable.
    // Le mot-clé "yield" est nécessaire pour bloquer l'exécution lors de l'attente de l'entrée utilisateur.
    username = yield ui.prompt('Entrez votre nom d'utilisateur');

    // Inviter l'utilisateur à entrer une valeur en lui indiquant une valeur par défaut.
    flavor = yield ui.prompt('Quel est votre parfum de glace préféré ?', 'Chocolat');

    // Inviter l'utilisateur à entrer des informations personnelles à l'aide de l'option "mask" et le champ de saisie est masqué lors de la saisie.
    // Si un paramètre n'est pas utilisé, la valeur "null" peut être utilisée pour indiquer qu'il ne doit pas être utilisé.
    // Nous illustrons ce principe ici en indiquant que nous n'avons pas besoin d'afficher une valeur par défaut.
    password = yield ui.prompt('Entrez votre mot de passe', null, true);

    // La fonction prompt renvoie la valeur null si l'utilisateur clique sur le bouton "Annuler" au lieu du bouton "OK".
    // Une façon de gérer cette situation est d'envelopper l'appel dans un bloc try/catch.
    scoops = yield ui.prompt('Combien de boules voulez-vous ?');
    if (scoops === null) {
      // Cette fonction quitte la macro.
      return;
      // Peut générer une erreur et l'intégrer dans l'objet "catch" ci-dessous.
     }
     // Utiliser les valeurs collectées pour commander une glace.
    ps.sendKeys(username + ControlKey.TAB + password + ControlKey.ENTER);
    yield wait.forCursor(new Position(5, 1));
    ps.sendKeys(flavor + ControlKey.TAB + scoops + ControlKey.ENTER);

    // Afficher un message à l'utilisateur. L'utilisation du mot-clé "yield" devant l'appel bloque
    // l'exécution ultérieure de la macro jusqu'à ce que l'utilisateur clique sur le bouton "OK".
    yield ui.message('Commande réussie. Bonne dégustation de vos ' + scoops + ' boules de glace ' + flavor + username + '!');
    } catch (error) {
     // Ici nous utilisons l'objet ui pour afficher un message signalant qu'une erreur s'est produite.
    yield ui.message(error.message);
    }
    // Fin de la macro générée

});

return macro();

Navigation dans les données

Cet exemple illustre comment naviguer entre un nombre variable d'écrans et traiter les données de chaque écran.

// Créer une fonction de macro.
var macro = createMacro(function*(){
  'use strict';

  // Créer des variables pour une utilisation ultérieure.
  var password;
  var accountNumber;
  var transactionCount = 0;
  var row = 0;

  // Obtenir une référence à l'objet PresentationSpace.
  var ps = session.getPresentationSpace();

  try {
    // Entrer le nom d'utilisateur et le mot de passe pour se connecter à l'application.
    yield wait.forCursor(new Position(19, 48));
    ps.sendKeys('bjones' + ControlKey.TAB);

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

    // Entrer une commande d'application.
    yield wait.forCursor(new Position(20, 38));
    ps.sendKeys('4');
    ps.sendKeys(ControlKey.ENTER);

    // Afficher les transactions pour un compte.
    yield wait.forCursor(new Position(13, 25));
    ps.sendKeys('2');
    // Entrer un numéro de compte. Codé en dur pour des raisons de simplicité.
    yield wait.forCursor(new Position(15, 25));
    accountNumber = yield ui.prompt('Numéro de compte :', '167439459');
    ps.sendKeys(accountNumber);
    ps.sendKeys(ControlKey.ENTER);

    // Attendre l'écran de profil de compte.
    yield wait.forText('PROFIL DE COMPTE', new Position(3, 33));

    // Rechercher du texte qui indique que la dernière page de l'enregistrement est atteinte.
    while (ps.getText(new Position(22, 12), 9) !== 'LAST PAGE') {

      // Tant que la dernière page de l'enregistrement n'est pas atteinte, accéder à la page suivante d'enregistrements.
      ps.sendKeys(ControlKey.PF2);
      yield wait.forCursor(new Position(1, 1));

      // Si la position du curseur ne change pas entre des écrans d'enregistrement, et qu'aucun texte
      // n'est affiché à l'écran, vous pouvez vérifier qu'un écran est mis à jour ou attendre
      // une période fixe après l'envoi d'une touche d'aide pour que l'écran se stabilise.
      // Par exemple :
      // yield wait.forFixedTime(1000);

      // Pour chacune des lignes, incrémenter la variable count si elle contient des données.
      for (row = 5; row <= 21; row++) { 

        // Il y a 2 colonnes à l'écran. Vérifier les données de la colonne 1.
        // Dans cet exemple, nous savons que la présence d'un espace à une
        // position particulière indique qu'il y a une transaction.
        if (ps.getText(new Position(row, 8), 1) !== ' ') {
          transactionCount++;
        }
        // Vérifier les données de la colonne 2.
        if (ps.getText(new Position(row, 49), 1) !== ' ') {
          transactionCount++;
        }
      }
    }

    // Après avoir parcouru toutes les pages d'enregistrement, afficher le nombre d'enregistrements dans une zone de message.
    yield ui.message(' + transactionCount + ' enregistrements ont été trouvés pour le compte ' + accountNumber + '.');

    // Déconnexion de l'application.
    ps.sendKeys(ControlKey.PF13);
    ps.sendKeys(ControlKey.PF12);

    // L'instruction try/catch permet de capturer toutes les erreurs et de les signaler à un emplacement centralisé.
  } catch (error) {
    // Nous utilisons ici l'objet ui pour afficher un message qui signale qu'une erreur s'est produite.
    yield ui.message(error.message);
  }
});

// Ici nous exécutons la macro et renvoyons les résultats dans l'outil d'exécution de macro.
// L'instruction return est requise, car l'application s'en
// sert pour déterminer si la macro a réussi.
return macro();

Appel d'un service Web

Cet exemple montre comment effectuer un appel AJAX/REST directement à partir d'une macro vers un service Web. Vous pouvez intégrer des données de votre application hôte à l'appel du service Web ou du service Web à votre application hôte.

Dans cet exemple, nous appelons le service REST Verastream Host Integrator (VHI) CICSAcctsDemo. Toutefois, vous pouvez facilement adapter le code pour appeler n'importe quel service Web. Vous n'êtes pas limité à VHI.

Dans l'exemple, l'appel passe par un proxy configuré sur le serveur de session (illustré ci-dessous) pour éviter une complication de type « même stratégie d'origine ». Si vous utilisez un service Web qui prend en charge le partage CORS (Cross-Origin Resource Sharing) et que vous utilisez un navigateur moderne, le proxy n'est pas nécessaire.

La bibliothèque jQuery étant disponible dans les macros, vous pouvez utiliser la fonction $.post() directement pour appeler des services REST.

Cet exemple montre également comment envelopper un appel REST jQuery dans un nouvel objet Promise. L'objet Promise renvoyé par la fonction personnalisée ci-dessous permet d'utiliser le mot-clé « yield » dans le code de la macro principale. Cela permet à l'exécution de la macro principale d'attendre la fin de l'appel de service avant de continuer.

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

  // Créer quelques variables pour une utilisation ultérieure.
  var username;
  var password;
  var accountNumber;
  var accountDetails;

  // Créer une fonction qui effectue un appel AJAX/REST au service Web VHI. 
  // Possibilité de l'ajuster pour appeler n'importe quel service Web, pas seulement VHI.
  // Si CORS n'est pas utilisé, la requête doit probablement transiter par 
  // un proxy sur le serveur de session. Pour plus d'informations, se reporter aux notes sur l'exemple.
  /**
   * Fonction d'aide codée à la main pour encapsuler les paramètres AJAX/REST, appeler le
   * service REST et renvoyer les résultats dans un objet Promise. 
   * @param {Number} Numéro de compte à envoyer à la requête REST.
   * @param {String} Nom d'utilisateur pour accéder au service REST.
   * @param {String} Mot de passe pour accéder au service REST.
   * @return {Promise} Contient les résultats $.post() compatibles avec yield.
  */
  var getAccountDetails = function (acctNum, username, password) 
    { var url = "proxy1/model/CICSAcctsDemo/GetAccountDetail";
    var args = {"filters": {"N° compte": acctNum}, "envVars": {"Nom d'utilisateur": username, "Mot de passe": password}};

    // Envelopper un appel jQuery AJAX/HTTP POST dans un nouvel objet Promise.
    // L'objet Promise renvoyé ici permet à la macro d'être générée/attendre
    // la fin d'exécution.
    return Promise.resolve($.post(url, JSON.stringify(args)))
      .catch(function (error) {
      // Assigner les erreurs qui se produisent dans l'appel jQuery à notre objet Promise.
      throw new Error('REST API Error: ' + error.statusText);
    });
  };

  // Début de la macro générée
  var ps = session.getPresentationSpace();
  try {
    // Possibilité d'interagir avec l'hôte ici, de se connecter à une application hôte, etc.
    // Collecter le nom d'utilisateur et le mot de passe
    username = yield ui.prompt('Nom d'utilisateur :');
    password = yield ui.prompt('Mot de passe :', null, true);
    accountNumber = yield ui.prompt('Numéro de compte :');
    if (!username || !password || !accountNumber) {
      throw new Error('Nom d'utilisateur ou mot de passe non spécifié');
    }

    // Appeler un service REST externe et générer/attendre la fin de l'appel.
    accountDetails = yield getAccountDetails(accountNumber, username, password);

    // Nous disposons à présent des données de notre service externe.
    // Possibilité d'intégrer les données dans notre application hôte locale ou de les afficher pour l'utilisateur.
    // Pour cet exemple, nous affichons simplement les détails du compte correspondant.
    if (accountDetails.result && accountDetails.result.length > 0) {
      yield ui.message(accountDetails.result[0].FirstName + ' $' + accountDetails.result[0].AcctBalance);
    } else {
      yield ui.message('Aucun enregistrement trouvé pour le compte : ' + accountNumber);
    }
  } catch (error) { 
    // Si une erreur se produit pendant l'appel AJAX/REST
    // ou la collecte du nom d'utilisateur/mot de passe, nous aboutissons ici.
    yield ui.message(error.message);
  }
});

// Exécution de notre macro.
return macro();

Prise en charge du proxy de script entre origines

Si vous avez des services Web qui ne prennent pas en charge CORS, les appels AJAX/REST échouent s'ils tentent d'accéder à un serveur autre que celui d'où provient l'application Host Access for the Cloud. Il s'agit d'une fonction de sécurité du navigateur.

Le serveur Host Access for the Cloud permet d'effectuer un proxy explicite vers les serveurs distants approuvés.

  • Ouvrez ..\<install_dir>\sessionserver\microservice\sessionserver\service.yml à des fins de modification.

  • Dans la section env, ajoutez :

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

    proxy-path correspond à l'assignation d'URL souhaitée et proxy-to-address à l'URL vers laquelle le proxy de l'appel est effectué.

  • Dans cet exemple :

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

    Les appels effectués <server:port>/proxy1 sont mis en proxy vers http://remote-vhi-server:9680/vhi-rs/.

  • Il est possible de spécifier plusieurs assignations de proxy en les séparant par une virgule.

  • N'oubliez pas que même lorsqu'un serveur REST prend en charge les en-têtes CORS, il se peut que certains navigateurs plus anciens ne le fassent pas. Cet exemple peut donc toujours être pertinent.

conseil

Votre fichier service.yml peut être remplacé lorsque vous redéployez Host Access for the Cloud. Effectuez dès lors toujours une sauvegarde de vos fichiers.

Utilisation des cellules de données et des attributs

Cette macro indique comment utiliser DataCells et AttributeSet pour inspecter le texte et les attributs d'une ligne/colonne donnée à l'écran. Dans cet exemple, vous pouvez constater :

  • Comment obtenir une collection de DataCells pour une position et une longueur données.

  • Comment itérer DataCells pour créer une chaîne de texte.

  • Comment vous pouvez également effectuer une opération similaire à l'aide de getText() à des fins de comparaison.

  • Enfin, comment utiliser des attributs, obtenir une liste de chaînes ou déterminer si des attributs spécifiques sont définis à un emplacement d'écran donné.

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

    // Obtenir l'objet PresentationSpace pour interagir avec l'hôte.
    var ps = session.getPresentationSpace();

    // Déclarer des variables pour une utilisateur ultérieure.
    var cells;
    var text;
    var attrs;

    // Définir le timeout par défaut pour les fonctions "wait".
    wait.setDefaultTimeout(10000);

    // Exemple de macro pour utiliser des objets DataCells et Attributes
    try {
        yield wait.forCursor(new Position(24, 2));

        // Obtenir des objets DataCells pour l'espace de présentation.
    // La ligne 19, colonne 3 est l'invite, longueur de 35 caractères.
    // "Choisissez l'une des commandes suivantes :"
    cells = ps.getDataCells({row:19, col:3}, 35); 
    text = '';

    // Vous pouvez afficher du texte avec getText.
    yield ui.message("Texte d'écran : " + ps.getText({row:19, col:3}, 35));

    // Vous pouvez aussi assembler le texte de DataCells à chaque position.
    for(var index = 0; index < cells.length; index++) {
            text = text.concat(cells[index].getChar());
    }
    // Et afficher le texte.
    yield ui.message("Texte des cellules : " + text);

    // Obtenir les attributs pour le premier objet DataCell. (cell[0])
    attrs = cells[0].getAttributes();

    // Afficher si nous avons des attributs dans la cellule de données.
    yield ui.message("Jeu d'attributs vide : " + attrs.isEmpty());

    // Afficher le nombre d'attributs définis.
    yield ui.message("Nombre d'attributs : " + attrs.size());

    // Afficher les attributs définis.
    yield ui.message("Attributs : " + attrs.toString());

    // Afficher à présent si l'attribut à haute intensité est défini.
    yield ui.message("Haute intensité : "
                         + attrs.contains(Attribute.HIGH_INTENSITY));

    // Afficher à présent si l'attribut souligné est défini.
    yield ui.message("Souligné : "
                         + attrs.contains(Attribute.UNDERLINE));

    // Afficher à présent si des attributs alphanumériques, intensifiés et détectables par stylet sont définis.
    yield ui.message("Alphanumérique, intensifié et détectable par stylet : " +
                         attrs.containsAll([Attribute.ALPHA_NUMERIC, Attribute.HIGH_INTENSITY, Attribute.PEN_DETECTABLE]));

    // Afficher à présent si des attributs soulignés, intensifiés et détectables par stylet sont définis.
    yield ui.message("Souligné, intensifié et détectable par stylet : " +
                         attrs.containsAll([Attribute.UNDERLINE, Attribute.HIGH_INTENSITY, Attribute.PEN_DETECTABLE]));
    } catch (error) {
        yield ui.message(error); 
    }
    // Fin de la macro générée
});

// Exécuter la macro.
return macro();

Utilisation de champs et de listes de champs

Cet exemple de macro illustre comment utiliser des fonctions courantes pour interagir avec les champs de l'API Macro. Par exemple, comment obtenir le texte d'un champ, afficher les informations d'un champ et utiliser field.setText comme solution alternative à sendKeys pour interagir avec l'hôte.

remarque

En raison de considérations relatives au navigateur, ui.message réduit les chaînes d'espaces en un seul espace. Les espaces sont conservés dans le code JavaScript réel.

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

    // Obtenir l'objet PresentationSpace pour interagir avec l'hôte.
    var ps = session.getPresentationSpace(); 

    // Déclarer des variables pour une utilisation ultérieure.
    var fields;
    var field;
    var searchString = 'z/VM';

    // Définir le timeout par défaut pour les fonctions "wait".
    wait.setDefaultTimeout(10000); 

    // Exemple de macro pour utiliser FieldList et Fields.
    try {
        yield wait.forCursor(new Position(24, 2));

    // Obtenir la liste de champs.
    fields = ps.getFields();

    // Parcourir toute la liste de champs et afficher les informations des champs.
    for(var index = 0; index < fields.size(); index++) {
            field = fields.get(index);

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

    yield ui.message("Rechercher à présent un champ contenant le texte '" + searchString + "'");
    field = fields.findField(new Position(1, 1), searchString);

    if(field !== null) {
            yield ui.message("Informations du champ trouvé : " + field.toString());
        yield ui.message("Le premier plan du champ trouvé est vert ? " + (Color.GREEN === field.getForegroundColor()));
        yield ui.message("L'arrière-plan du champ trouvé est par défaut ? " + (Color.BLANK_UNSPECIFIED === field.getBackgroundColor()));
    }

    // Rechercher à présent un champ de commande et le modifier.
    field = fields.findField(new Position(23, 80));
    if(field !== null) {
            field.setText("cics");
    }

    yield ui.message("Cliquez pour envoyer 'cics' à l'hôte.");
    ps.sendKeys(ControlKey.ENTER); 

    // Attendre un nouvel écran, obtenir de nouveaux champs.
    yield wait.forCursor(new Position(10, 26));
    fields = ps.getFields();

    // Rechercher un champ d'utilisateur et le définir.
    field = fields.findField(new Position(10, 24));
    if(field !== null) {
            field.setText("nom_utilisateur");
    }

    // Rechercher un champ de mot de passe et le définir.
    field = fields.findField(new Position(11, 24));
    if(field !== null) { 
            field.setText("mot_passe");
    }

    yield ui.message("Cliquez pour envoyer la connexion à l'hôte.");
    ps.sendKeys(ControlKey.ENTER);

    // Attendre un nouvel écran, obtenir de nouveaux champs.
    yield wait.forCursor(new Position(1, 1));
    fields = ps.getFields();

    // Rechercher un champ de commande et définir la commande de déconnexion.
    field = fields.findField(new Position(24, 45));
    if(field !== null) {
            field.setText("cesf logoff");
    }

    yield ui.message("Cliquez pour envoyer la déconnexion à l'hôte.");
    ps.sendKeys(ControlKey.ENTER);

   } catch (error) {
        yield ui.message(error);
    }
    // Fin de la macro générée
});

// Exécuter la macro.
return macro();

Macro d'ouverture de session automatique pour les mainframes

Dans cet exemple, l'objet Autosignon sert à créer une macro qui utilise les informations d'identification associées à un utilisateur pour obtenir un ticket d'accès à partir du serveur DCAS (Digital Certificate Access Server).

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

    // Obtenir l'objet PresentationSpace pour interagir avec l'hôte.
    var ps = session.getPresentationSpace();

    // Variable pour le ticket d'accès de connexion.
    var passTicket;

    // ID d'application de connexion.
    var appId = 'CICSV41A';

    // Définir le timeout par défaut pour les fonctions "wait".
    wait.setDefaultTimeout(10000);

    // Début de la macro générée
    try { 
        yield wait.forCursor(new Position(24, 2));

    // Obtenir un ticket d'accès depuis DCAS.
    passTicket = yield autoSignon.getPassTicket(appId);

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

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

    // Remplacer le nom d'utilisateur généré par sendUserName(passTicket) ...
    yield autoSignon.sendUserName(passTicket); 

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

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

    // Remplacer le mot de passe généré par sendPassword(passTicket) ... 
    yield autoSignon.sendPassword(passTicket);

    // var userInput3 = yield ui.prompt('Mot de passe :', '', true);
    // if (userInput3 === null) {
            // throw new Error('Mot de passe non fourni');
    // }
    // ps.sendKeys(userInput3);
    ps.sendKeys(ControlKey.ENTER);

    yield wait.forCursor(new Position(1, 1));
    yield ui.message('Connecté. Se déconnecter.');
    ps.sendKeys('cesf logoff');
    ps.sendKeys(ControlKey.ENTER); 
    } catch (error) {
    yield ui.message(error);
    }
    // Fin de la macro générée
}); 

// Exécuter la macro.
return macro();

Utilisation du transfert de fichiers (IND$File)

Cette série d'exemples de macros montre comment utiliser l'API de transfert de fichiers pour récupérer une liste de fichiers, télécharger un fichier et charger un fichier vers un hôte 3270.

remarque

Vous devez être connecté et être à une invite avant d'exécuter ces macros.


Répertorier des fichiers

Cette macro explique comment utiliser l'API de transfert de fichiers pour récupérer une liste de fichiers sur un hôte 3270 à l'aide du transfert IND$File. L'objet de transfert IND$File est récupéré de l'usine de transfert de fichiers, puis utilisé pour obtenir un tableau d'objets HostFile depuis TSO ou CMS.

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

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

        yield ui.message(' + hostFiles.length + ' fichiers trouvés');
    if (hostFiles.length > 0) {
            var firstFile = hostFiles[0];
        var msg1 = 'Le nom du catalogue est ' + firstFile.getParent() + '. ';
        var msg2 = 'Le premier fichier est ' + firstFile.getName();
        yield ui.message(msg1 + msg2);
    }
    } catch (error) {
        yield ui.message(error);
    }
});

// Exécuter la macro.
return macro();

Télécharger un fichier

Cette macro indique comment utiliser l'API de transfert de fichiers pour télécharger un fichier à partir d'un hôte 3270 à l'aide du transfert IND$File. L'objet de transfert IND$File est récupéré de l'usine de transfert de fichiers. Dans cet exemple, la méthode de transfert est définie sur ASCII pour démontrer l'utilisation de la fonction setTransferOptions.

L'exemple de macro télécharge le premier fichier renvoyé par un appel à getHostFileListing en créant un URI de téléchargement avec un appel à la fonction getDownloadUrl. La macro peut être utilisée dans un environnement CMS ou TSO, mais l'option doit être spécifiée sur la première ligne ou le code modifié légèrement pour le système prévu.

var hostEnvironment = 'CMS'; // 'TSO'
// Construire le chemin de fichier, catalogue/nom.fichier ou catalogue/partition/fichier
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();

    // Les options transferMethod sont 'binary' et 'ascii'. 
    fileTransfer.setTransferOptions({transferMethod: 'ascii'});

    // Cette démo récupère le premier fichier renvoyé dans la liste. 
    var hostFiles = yield fileTransfer.getHostFileListing(); 
    var firstHostFile = hostFiles[0];

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

    // Télécharger.
    // Si vous connaissez déjà le chemin du fichier souhaité, transmettez-le à getDownloadURL().
    var downloadUrl = fileTransfer.getDownloadURL(getPath(firstHostFile));

    // Modifie l'emplacement du navigateur. Les résultats peuvent varier en fonction du navigateur utilisé.
    window.location = downloadUrl;

    // Si vous souhaitez lire le contenu du fichier dans une variable au lieu de le 
    // télécharger, vous pouvez utiliser jQuery
    // var fileContents = yield $.get(downloadUrl);

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

// Exécuter la macro.
return macro();

Charger un fichier

Cette macro indique comment utiliser l'API de transfert de fichiers pour charger un fichier vers un hôte 3270 à l'aide du transfert IND$File. L'exemple de macro invite l'utilisateur à choisir un fichier dans le système de fichiers local en déclenchant la boîte de dialogue de sélection de fichier du navigateur. Il récupère ensuite le catalogue actuel sur TSO ou l'identifiant de lecteur sur CMS en appelant getHostFileListing. Enfin, la fonction sendFile est appelée pour remettre le fichier local sélectionné à l'hôte.

La macro peut être utilisée dans un environnement CMS ou TSO, mais l'option doit être spécifiée sur la première ligne. Dans cet exemple, la méthode de transfert est définie sur ascii ; vous pouvez la remplacer par binary.

var hostEnvironment = 'CMS';
// 'TSO' // Ouvrir la boîte de dialogue de sélection de fichier du navigateur par programme. 
function promptForFileToUpload () { 
    return new Promise(function (resolve, reject) {
        // Pas de notification si l'utilisateur annule la boîte de dialogue de sélection de fichier. Rejet après 30 secondes.
    var timerId = setTimeout(reject.bind(null, 'Timeout lors de l'attente de la sélection du fichier'), 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();

    // Les options transferMethod sont 'binary' et 'ascii'.
     fileTransfer.setTransferOptions({transferMethod: 'ascii'}); 

     var localFile = yield promptForFileToUpload();

     // Récupérer le nom du catalogue actuel et y ajouter le nom du fichier sélectionné.
     var hostFiles = yield fileTransfer.getHostFileListing();
     var destination = hostFiles[0].getParent() + '/' + localFile.name;

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

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

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

// Exécuter la macro.
return macro();