action.skip

Ejemplos de Macros

Para ayudarle a crear correctamente macros que se beneficien de todas las funciones del Editor de macros, dispone de estos ejemplos como punto de partida.

Interacción Básica con el Host

Este ejemplo muestra la interacción básica con el host, incluyendo:

  • Enviar datos al host
  • Esperar pantallas a mostrar
  • Utilizar la palabra clave yield para esperar funciones asíncronas
  • Leer texto de la pantalla
  • Mostrar información básica al usuario
  • Tratamiento de errores básicos

Todas las macros tienen disponibles los siguientes objetos de forma predeterminada:

  1. session: punto de entrada principal para acceder al host. Puede conectar, desconectar y facilitar acceso al PresentationSpace.

    El objeto PresentationSpace obtenido de la sesión representa la pantalla y proporciona muchas funciones comunes, como obtener y establecer la ubicación del cursor, enviar datos al host y leer de la pantalla.

  2. wait: facilita una forma sencilla de esperar a varios estados del host antes de seguir enviando más datos o leer de la pantalla.

  3. UI: ofrece funciones básicas de interfaz de usuario. Muestra datos al usuario o le pide información.

    // Función Crear una nueva macro
    var macro = createMacro(function*(){
    'use strict';
    
    // Todas las macros tienen disponibles los siguientes objetos de forma predeterminada:
    // 1. session - Punto de entrada principal para acceder al host. Puede conectar, desconectar y facilitar acceso al PresentationSpace.
    //    El objeto PresentationSpace obtenido de la sesión representa la pantalla y provee capacidades muy comunes como obtener y ajustar la
    //    posición del cursor, enviar datos al host y leer de la pantalla.
    // 2. wait - Facilita una forma sencilla de esperar a varios estados del host antes de seguir enviando más datos o leer de la pantalla.
    // 3. uiI - Provee capacidades básicas de interfaz de usuario. Mostrar datos al usuario o pedirle información.
    
    // Declarar una variable para leer y visualizar algunos datos de pantalla.
    // La mejor práctica es declarar todas las variables cerca de la parte superior de una función.
    var numberOfAccounts = 0;
    
    // Iniciar obteniendo el objeto PresentationSpace, que provee muchas operaciones de pantalla comunes.
    var ps = session.getPresentationSpace();
    
    try {
        // Puede ajustar y obtener la posición del cursor
        ps.setCursorPosition(new Position(24, 2));
    
        // Utilizar la función sendKeys para enviar caracteres al host 
        ps.sendKeys('cics');
    
        // SendKeys se utiliza también para enviar teclas de host como teclas PA y PF.
        // Véase "Control Keys" en la documentación para todas las opciones disponibles 
        ps.sendKeys(ControlKey.ENTER);
    
        // Esperar a que el cursor se encuentre en la posición correcta.
        // El objeto wait provee varias funciones para esperar a que ocurran determinados estados
        // de modo que usted pueda proceder o bien a enviar más teclas, o bien a leer datos de la pantalla. 
        yield wait.forCursor(new Position(24, 2));
    
        // Puede mezclar caracteres y teclas de control en una llamada sendKeys. 
        ps.sendKeys('data' + ControlKey.TAB + ControlKey.TAB + 'more data' + ControlKey.ENTER);
    
        // La palabra clave "yield" se debe utilizar enfrente de todas las llamadas de función "wait" y "ui".
        // Le dice al navegador que detenga la ejecución de la macro hasta que la
        // función wait (asíncrona) vuelva. Consulte la documentación para saber qué funciones
        // requieren la palabra clave yield. 
        yield wait.forCursor(new Position(10, 26)); 
        ps.sendKeys('accounts' + ControlKey.ENTER);
    
        // Puede esperar también a que aparezca un texto en ciertas áreas de la pantalla 
        yield wait.forText('ACCOUNTS', new Position(3, 36)) ; 
        ps.sendKeys('1' + ControlKey.ENTER);
    
        // Todas las funciones wait excederán el tiempo de espera si no se cumplen los criterios dentro de un límite de tiempo.
        // Puede incrementar tiempos de espera con un parámetro opcional en las funciones wait (en milisegundos)
        // Todos los tiempos de espera se especifican en milisegundos y el valor predeterminado es 10 segundos (10000 ms). 
        yield wait.forCursor(new Position(1, 1), 15000); 
        ps.sendKeys('A' + ControlKey.ENTER);
    
        // PS proporciona la función getText para leer texto de la pantalla
        numberOfAccounts = ps.getText(new Position(12, 3), 5);
    
        // Utilizar el objeto ui para visualizar algunos datos de la pantalla
        ui.message('Número de cuentas activas: ' + numberOfAccounts);
    
        // La try / catch permite capturar todos los errores y notificarlos a una ubicación central
    } catch (error) {
        // De nuevo, utilizamos el objeto ui para visualizar un mensaje que indica que se ha producido un error
        yield ui.message('Error: ' + error.message);
    }
    //Fin Macro Generada
    });
    
    // Ejecutar la macro y devolver los resultados al Ejecutor de macros
    // La instrucción return es necesaria, ya que la aplicación aprovecha
    // esto para saber si la macro se ha ejecutado correctamente y cuándo ha finalizado
    return macro();
    

Interacción con el usuario

Este ejemplo ilustra cómo utilizar los métodos API provistos para pedirle entradas al usuario o para alertarle con un mensaje.

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

  // El objeto "ui" ofrece funciones para preguntar información al usuario y para mostrar información

  // Declarar variables para uso posterior
  var username;
  var password;
  var flavor;
  var scoops;

  //Inicio Macro Generada
  var ps = session.getPresentationSpace();

  try {
    // Pedir al usuario que ingrese su nombre de usuario y guardarlo en una variable.
    // Recuerde que la palabra clave 'yield' es necesaria para bloquear la ejecución mientras se espera a la entrada del usuario.
    username = yield ui.prompt(‘Introduzca su nombre de usuario');

    // Pide al usuario ingresar un valor predeterminado que se le ha facilitado.
    flavor = yield ui.prompt('¿Cuál es su helado favorito?', 'Chocolate');

    // Pide al usuario ingresar información privada cuando se utiliza la opción 'mask' y el campo de entrada se enmascarará mientras escribe.
    // Si el parámetro no se utiliza, se puede utilizar 'cero' para especificar que no se desea utilizar.
    // Aquí lo ilustramos especificando que no necesitamos mostrar un valor predeterminado.
    password = yield ui.prompt('Introduzca su contraseña', null, true);

    // La función de preguntar devuelve cero si el usuario hace clic en el botón 'Cancelar' en lugar de en el botón 'Aceptar'.
    // Una forma de tratar este caso es ajustar la llamada a un bloque try/catch.
    scoops = yield ui.prompt('¿Cuántas cucharadas quiere?');
    if (scoops === null) {
      // Se sale de la macro.
      return;
      // Alternativamente podría arrojar un Error y capturarlo en el "catch" situado a continuación
     }
     // Utilizar los valores coleccionados para pedir nuestro ice cream 
    ps.sendKeys(username + ControlKey.TAB + password + ControlKey.ENTER); 
    yield wait.forCursor(new Position(5, 1)); 
    ps.sendKeys(flavor + ControlKey.TAB + scoops + ControlKey.ENTER);

     // Mostrar un mensaje al usuario. Utilizando la palabra clave 'yield' enfrente de la llamada bloquea
     // la ejecución de la macro hasta que el usuario hace clic en el botón 'Aceptar'.
    yield ui.message('Orden correcta. Enjoy your ' + scoops + ' scoops of ' + flavor + ' ice cream ' + username + '!');
    } catch (error) {
     // Aquí utilizamos el objeto ui para mostrar un mensaje de que ha ocurrido un error
    yield ui.message(error.message);
    }
    //Fin Macro Generada

});

return macro();

Navegar Por Datos

Este ejemplo explica cómo navegar por un número variable de pantallas y procesar los datos en cada pantalla.

 // Función Crear una nueva macro.
var macro = createMacro(function*(){
  'use strict';

  // Crear variable(s) para uso posterior
  var password;
  var accountNumber;
  'var transactionCount = 0;
  var row = 0;

  // Obtener una referencia para el objeto PresentationSpace.
  var ps = session.getPresentationSpace(); 

  try {
    // Introducir nombre de usuario y contraseña para iniciar sesión en la aplicación. 
    yield wait.forCursor(new Position(19, 48)); 
    ps.sendKeys('bjones' + ControlKey.TAB); 

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

    // Introducir un comando de aplicación. 
    yield wait.forCursor(new Position(20, 38)); 
    ps.sendKeys('4'); 
    ps.sendKeys(ControlKey.ENTER);

    // Ir a la lista de transacciones para una lista. 
    yield wait.forCursor(new Position(13, 25)); 
    ps.sendKeys('2');
    // Ingresar un número de cuenta. Codificación fija aquí para simplificar. 
    yield wait.forCursor(new Position(15, 25));
    accountNumber = yield ui.prompt('Número de cuenta:', '167439459'); 
    ps.sendKeys(accountNumber); 
    ps.sendKeys(ControlKey.ENTER);

    // Esperar hasta que esté en pantalla de perfil de cuenta 
    yield wait.forText('ACCOUNT PROFILE', new Position(3, 33));

    // Buscar texto que indique que la última página de la grabación se ha alcanzado mientras
    while (ps.getText(new Position(22, 12), 9) !== 'LAST PAGE') {

      // Mientras que la página de la grabación no se haya alcanzado, ir a la siguiente página de grabaciones. 
      ps.sendKeys(ControlKey.PF2); 
      yield wait.forCursor(new Position(1, 1));

      // Si la posición del cursor no cambia entre las pantallas de grabación y no hay texto
      // en la pantalla, puede verificar si una pantalla se ha actualizado, puede esperar durante un
      // periodo de tiempo fijo después de que una tecla de ayuda haya sido enviada hasta el establecimiento de la pantalla.
      // Por ejemplo:
      // yield wait.forFixedTime(1000);

      // Para cada una de las pantallas, incremente la variable de recuento si contiene datos.
      for (row = 5; row <= 21; row++) {

        // Hay 2 columnas en la pantalla. Comprobar datos en columna 1.
        // En este ejemplo, sabemos que si hay un espacio en una posición
        // específica, se trata de una transacción.
        if (ps.getText(new Position(row, 8), 1) !== ' ') {
          transactionCount++;
        }
        // Comprobar datos en columna 2.
        if (ps.getText(new Position(row, 49), 1) !== ' ') {
          transactionCount++;
        }
      }
    }

    // Después de haber pasado por todas las páginas de grabación, mostrar el número de grabaciones en un cuadro de mensaje.
    yield ui.message('Encontradas ' + transactionCount + ' grabaciones para cuenta ' + accountNumber + '.');

    // Salir de la aplicación 
    ps.sendKeys(ControlKey.PF13); 
    ps.sendKeys(ControlKey.PF12);

    // La try / catch permite capturar todos los errores y notificarlos a una ubicación central
  } catch (error) {
    // Aquí utilizamos el objeto ui para visualizar un mensaje que indica que se ha producido un error
    yield ui.message(error.message);
  }
});

// Aquí ejecutamos la macro y devolvemos los resultados al Ejecutor de macros
// La instrucción return es necesaria, ya que la aplicación aprovecha
// esto para saber si la macro se ha ejecutado correctamente y cuándo ha finalizado
return macro();

Invocar un Servicio Web

Este ejemplo explica cómo realizar una llamada AJAX / REST desde una macro a un servicio web. Puede integrar datos desde su aplicación de host a la llamada del servicio web o desde el servicio web a su aplicación de host.

En este ejemplo llamamos el servicio Verastream Host Integrator (VHI) CICSAcctsDemo REST. En cualquier caso, puede adaptar fácilmente el código para llamar cualquier servicio web. No está limitado a VHI.

En el ejemplo, la llamada va a través de un proxy configurado en el servidor de sesión (mostrado más abajo) para evitar una complicación del tipo "Same Origin Policy" (Directiva del mismo origen). Si está utilizando un servicio web que soporte Cross-origin Resource Sharing (CORS) y está utilizando un navegador moderno, el proxy es innecesario.

Como la biblioteca jQuery está disponible en las macros, puede utilizar la función $.post() directamente para invocar servicios REST.

Este ejemplo explica también cómo ajustar una llamada jQuery REST en una nueva Promise. La promise devuelta por la función personalizada siguiente permite utilizar "yield" en el código de la macro principal. Esto permite que la ejecución de la macro espere hasta que la llamada de servicio se complete antes de continuar.

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

  // Crear unas cuantas variables para usuario posterior
  var username;
  var password;
  var accountNumber;
  var accountDetails;

  // Crear una función que hará una llamada AJAX / REST a un servicio web VHI.
  // Se podría ajustar para llamar cualquier servicio web, no sólo VHI.
  // Si no se utiliza CORS, la solicitud tendría que pasar por un
  // proxy en el servidor de sesión. Véanse notas de ejemplo para más información.
  /**
   * Función de auxiliar de cifrado manual para encapsular parámetros AJAX / REST, invocar el servicio
   * REST y devolver los resultados dentro de una Promise.
   * @param {Number} acctNum para enviar a la consulta REST.
   * @param {String} nombre de usuario para acceder al servicio REST.
   * @param {String} contraseña para acceder al servicio REST.
   * @return {Promise} que contiene resultados $.post() compatibles con yield.
   */
  var getAccountDetails = function (acctNum, username, password) {
    var url = "proxy1/model/CICSAcctsDemo/GetAccountDetail";
    var args = {"filters": {"AcctNum": acctNum}, "envVars": {"Username": username, "Password": password}};

    // Ajustar una llamada jQuery AJAX / HTTP POST en una nueva Promise.
    // La promise que se devuelve aquí permite a la macro yield / esperar
    // hasta que se complete.
    return Promise.resolve($.post(url, JSON.stringify(args)))
      .catch(function (error) {
      // Se han producido errores de asignación en la llamada jQuery a nuestra Promise.
      throw new Error('REST API Error: ' + error.statusText);
    });
  };

  // Inicio Macro Generada
  var ps = session.getPresentationSpace();
  try {
    // Podría interactuar con el host aquí, iniciar sesión en app de host, etc...
    // Recuperar nombre de usuario y contraseña
    username = yield ui.prompt('Nombre de usuario:');
    password = yield ui.prompt('Contraseña:', null, true);
    accountNumber = yield ui.prompt('Número de cuenta:');
    if (!username || !password || !accountNumber) {
      throw new Error('Username or password not specified');
    }

    // Invocar servicio REST externo, y yields / esperar a que se complete la llamada.
    accountDetails = yield getAccountDetails(accountNumber, username, password);

    // Ahora tenemos los datos de nuestro servicio externo.
    // Puede integrar los datos en nuestra app de host local o simplemente mostrarlos al usuario.
    // En este ejemplo sólo mostramos los detalles de la cuenta resultantes.
    if (accountDetails.result && accountDetails.result.length > 0) {
      yield ui.message(accountDetails.result[0].FirstName + ' $' + accountDetails.result[0].AcctBalance);
    } else {
      yield ui.message('Ninguna grabación encontrada para cuenta: ‘ + accountNumber);
    }
  } catch (error) {
    // Si se ha producido un error durante la llamada AJAX / REST call
    // o la recuperación del nombre de usuario / contraseña terminaremos aquí.
    yield ui.message(error.message);
  }
});

// Ejecutar nuestra macro
return macro();

Cross Origin Scripting Proxy Support

Si tiene servicios web que no admiten CORS, las llamadas a AJAX/REST presentarán errores si intentan acceder a un servidor distinto a aquel en el que se originó la aplicación Host Access for the Cloud. Esta es una función de seguridad del navegador.

El servidor de Host Access for the Cloud proporciona un método explícito para establecer un proxy en servidores remotos de confianza.

  • Abra ..\<directorio_de_instalación>\sessionserver\microservice\sessionserver\service.yml para editarlo.

  • En la sección env, agregue:

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

    Donde proxy-path hace referencia a la asignación de URL y proxy-to-address hace referencia a la URL en la que se redirigirá mediante proxy la llamada.

  • En este ejemplo:

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

    Las llamadas realizadas a <servidor:puerto>/proxy1 se redirigirán mediante apoderado (proxy) a http://remote-vhi-server:9680/vhi-rs/.

  • Se pueden especificar varias asignaciones de proxy utilizando una coma para separar las asignaciones de proxy individuales.

  • Recuerde que incluso si un servidor REST soporta encabezados CORS, algunos navegadores antiguos pueden no soportarlos, por lo que este ejemplo sigue siendo relevante.

Sugerencia

Es posible que el archivo service.yml se sustituya cada vez que distribuya de nuevo Host Access for the Cloud. Haga siempre una copia de seguridad de sus archivos.

Trabajar con celdas de datos y atributos

Esta macro explica cómo usar DataCells y AttributeSet para inspeccionar una fila/columna en la pantalla para texto y atributos. En este ejemplo puede ver:

  • Cómo obtener una colección de DataCells para una posición y longitud dadas.

  • Cómo iterar por DataCells para formar una cadena de texto

  • Para comparar, cómo puede hacer algo similar utilizando getText().

  • Y finalmente, cómo trabajar con atributos, obtener un listado de cadenas o determinar si cadenas específicas están colocadas en una posición dada de la pantalla.

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

    // Obtener PresentationSpace para interactuar con el host
    var ps = session.getPresentationSpace();

    // Declarar variables para uso posterior
    var cells;
    var text;
    var attrs;

    // Establecer el tiempo de espera predeterminado para las funciones "wait"
    wait.setDefaultTimeout(10000);

    // Macro de ejemplo para trabajar con DataCells y Attributes
    try { 
        yield wait.forCursor(new Position(24, 2));

        // Obtener DataCells del espacio de presentación.
        // Fila 19, col 3 es la pregunta, 35 caracteres de longitud
        // "Seleccionar de los siguientes comandos:"
        cells = ps.getDataCells({row:19, col:3}, 35);
        text = '';

        // Puede visualizar texto utilizando getText
        yield ui.message("Screen text: " + ps.getText({row:19, col:3}, 35));

        // O puede ensamblar el texto de las DataCells en cada posición
        for(var index = 0; index < cells.length; index++) {
            text = text.concat(cells[index].getChar());
        }
        // Y visualizar el texto
        yield ui.message("Cells text: " + text);

        // Obtener los atributos de la primera DataCell (cell[0])
        attrs = cells[0].getAttributes();

        // Muestra si hay o no atributos en la celda de datos
        yield ui.message("Conjunto de atributos vacío: " + attrs.isEmpty());

        // Muestra cuántos atributos están configurados
        yield ui.message("Número de atributos: " + attrs.size());

        // Muestra qué atributos están configurados
        yield ui.message("Atributos: " + attrs.toString());

        // Mostrar ahora si el atributo de alta intensidad está configurado
        yield ui.message("Es de alta intensidad: " +
                         attrs.contains(Attribute.HIGH_INTENSITY));

        // Mostrar ahora si el atributo subrayado está configurado
        yield ui.message("Es subrayado: " +
                         attrs.contains(Attribute.UNDERLINE));

        // Mostrar ahora si los atributos alfanumérico, intensificado y detectable por lápiz están configurados
        yield ui.message("Es alfanumérico, intensificado y detectable por lápiz: " +
                         attrs.containsAll([Attribute.ALPHA_NUMERIC, Attribute.HIGH_INTENSITY, Attribute.PEN_DETECTABLE]));

        // Mostrar ahora si los atributos alfanumérico, intensificado y detectable por lápiz están configurados
        yield ui.message("Es alfanumérico, intensificado y detectable por lápiz: " +
                         attrs.containsAll([Attribute.UNDERLINE, Attribute.HIGH_INTENSITY, Attribute.PEN_DETECTABLE]));
    } catch (error) {
        yield ui.message(error);
    }
    //Fin Macro Generada
});

// Ejecutar la macro
return macro();

Utilizar Campos y Listas de Campos

Este ejemplo de macro explica cómo utilizar funciones comunes para interactuar con los campos de la Macro API. Por ejemplo, cómo obtener texto de campo, ver información de campo y utilizar field.setText como alternativa a sendKeys para interactuar con el host.

Nota

Debido a las consideraciones del navegador, ui.message contrae cadenas de espacios a un solo espacio. Los espacios se preservan en el JavaScript actual.

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

    // Obtener PresentationSpace para interactuar con el host
    var ps = session.getPresentationSpace();

    // Declarar variables para uso posterior
    var fields;
    var field;
    var searchString = 'z/VM';

    // Establecer el tiempo de espera predeterminado para las funciones "wait"
    wait.setDefaultTimeout(10000);

    // Macro de ejemplo para trabajar con FieldList y Fields
    try {
    yield wait.forCursor(new Position(24, 2));

    // Obtener la lista de campos.
    fields = ps.getFields();

        // Ejecutar en toda la lista de campos y mostrar la información del campo.
        for(var index = 0; index < fields.size(); index++) {
            field = fields.get(index);

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

        yield ui.message("Ahora, encontrar un campo que contenga el texto '" + searchString + "'");
        field = fields.findField(new Position(1, 1), searchString);

        if(field !== null) {
            yield ui.message("Found field info: " + field.toString());
            yield ui.message(“¿Encontrado primer plano de campo es verde? " + (Color.GREEN === field.getForegroundColor()));
            yield ui.message("¿Encontrado primer plano de campo es predeterminado? " + (Color.BLANK_UNSPECIFIED === field.getBackgroundColor()));
        }

        // Ahora, encontrar campo de comando y modificarlo.
        field = fields.findField(new Position(23, 80));
        if(field !== null) {
             field.setText("cics");
        }

        yield ui.message("Clic para enviar 'cics' al host."); 
        ps.sendKeys(ControlKey.ENTER);

        // Esperar a nueva pantalla; obtener nuevos campos. 
        yield wait.forCursor(new Position(10, 26));
        fields = ps.getFields();

        // Encontrar campo de usuario y configurarlo.
        field = fields.findField(new Position(10, 24));
        if(field !== null) {
            field.setText("myusername");
        }

        // Encontrar campo de contraseña y configurarlo.
        field = fields.findField(new Position(11, 24));
        if(field !== null) {
            field.setText("mypassword");
        }

        yield ui.message("Clic para enviar inicio de sesión al host."); 
        ps.sendKeys(ControlKey.ENTER);

        // Esperar a nueva pantalla; obtener nuevos campos. 
        yield wait.forCursor(new Position(1, 1));
        fields = ps.getFields();

        // Encontrar campo de comando y configurar comando logoff.
        field = fields.findField(new Position(24, 45));
        if(field !== null) {
            field.setText("cesf logoff");
        }

        yield ui.message("Clic para enviar logoff al host."); 
        ps.sendKeys(ControlKey.ENTER);

    } catch (error) {
        yield ui.message(error);
    }
    //Fin Macro Generada
});

// Ejecutar la macro
return macro();

Macro Sign-On automático para Mainframes

En este ejemplo se utiliza el objeto AutoSignon para crear una macro que utiliza las credenciales asociadas a un usuario para obtener un ticket de paso del Digital Certificate Access Server (servidor de acceso a certificados digitales, DCAS).

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

    // Obtener PresentationSpace para interactuar con el host
    var ps = session.getPresentationSpace();

    // Variable para ticket de paso de inicio de sesión
    var passTicket;

    // ID de inicio de sesión en aplicación
    var appId = 'CICSV41A';

    // Establecer el tiempo de espera predeterminado para las funciones "wait"
    wait.setDefaultTimeout(10000);

    // Inicio Macro Generada
    try { 
        yield wait.forCursor(new Position(24, 2));

        // Obtener un ticket de paso de DCAS.
        passTicket = yield autoSignon.getPassTicket(appId); 

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

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

        // Sustituir nombre de usuario generado por 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));

        // Sustituir contraseña generada por sendPassword(passTicket) ... 
        yield autoSignon.sendPassword(passTicket);

        // var userInput3 = yield ui.prompt('Contraseña:', '', true);
        // if (userInput3 === null) {
            // throw new Error('Password not provided');
        // }
        // ps.sendKeys(userInput3);
        ps.sendKeys(ControlKey.ENTER);

        yield wait.forCursor(new Position(1, 1));
        yield ui.message('Logged in. Log me off.'); 
        ps.sendKeys('cesf logoff'); 
        ps.sendKeys(ControlKey.ENTER);
    } catch (error) {
        yield ui.message(error);
    }
    //Fin Macro Generada
});

// Ejecutar la macro
return macro();

Utilizar Transferencia de Archivos (IND$File)

Esta serie de ejemplos de macros demuestra cómo utilizar la API de transferencia de archivos para recuperar una lista de archivos, descargar un archivo y cargar un archivo a un host 3270.

Nota

Debe haber iniciado sesión y tener una indicación de sistema abierta antes de ejecutar estas macros.


List archivos

Esta macro muestra cómo utilizar la API de transferencia de archivos para recuperar una lista de archivos de un host 3270 utilizando la transferencia IND$File. El objeto de transferencia IND$File se recupera de la transferencia de archivos de fábrica y se utiliza para obtener una matriz de objetos HostFile de TSO o de CMS.

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 = 'El nombre del catálogo es ' + firstFile.getParent() + '. ';
            var msg2 = 'The first file is ' + firstFile.getName();
            yield ui.message(msg1 + msg2);
        }
    } catch (error) {
        yield ui.message(error);
    }
});

// Run the macro
return macro();

Descargar archivo

Esta macro muestra cómo utilizar la API de transferencia de archivos para descargar un archivo de un host 3270 utilizando la transferencia IND$File. El objeto de transferencia IND$File se recupera de la transferencia de archivos de fábrica. En este ejemplo, el método de transferencia se ha definido en ASCII para mostrar el uso de la función setTransferOptions.

La macro de ejemplo descarga el primer archivo devuelto desde una llamada a getHostFileListing, lo que crea un URI de descarga con una llamada a la función getDownloadUrl. La macro se puede utilizar en un entorno CMS o TSO, pero la opción debe especificarse en la primera línea o el código debe modificarse ligeramente para el sistema previsto.

var hostEnvironment = 'CMS';  // 'TSO'
// Construct file path, ie catalog/file.name or 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();

        // Las opciones de transferMethod son 'binario' y 'ascii'
        fileTransfer.setTransferOptions({transferMethod: 'ascii'});

        // Esta demostración recupera el primer archivo devuelto en la lista
        var hostFiles = yield fileTransfer.getHostFileListing();
        var firstHostFile = hostFiles[0];

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

        // Download
        // Si ya conoce la ruta al archivo que desea, pásela a getDownloadURL()
        var downloadUrl = fileTransfer.getDownloadURL(getPath(firstHostFile));

        // Esto cambia la ubicación del navegador. Puede obtener resultados diferentes en navegadores diferentes
        window.location = downloadUrl;

        // Si desea leer el contenido del archivo en una variable en lugar de descargarlo,
        // puede utilizar jQuery
        // var fileContents = yield $.get(downloadUrl);

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

// Run the macro
return macro();

Cargar archivo

Esta macro muestra cómo utilizar la API de transferencia de archivos para cargar un archivo a un host 3270 utilizando la transferencia IND$File. Esta macro de ejemplo pide al usuario seleccionar un archivo del sistema de archivos local activando el diálogo de selección de archivos del navegador. Éste recupera el catálogo actual en TSO o identificador de unidad en CMS llamando getHostFileListing. Por último, se llama a la función sendFile para entregar el archivo local seleccionado al host.

La macro se puede utilizar en un entorno CMS o TSO, pero la opción debe especificarse en la primera línea. En este ejemplo, el método de transferencia está ajustado a ascii; si lo desea, puede cambiarlo a binario.

var hostEnvironment = 'CMS';  // 'TSO'
// Abre la función programada de diálogo de selección de archivos del navegador
function promptForFileToUpload () {
    return new Promise(function (resolve, reject) {
        // No se nos notifica si el usuario camcela el ciálogo selector de archivos, por tanto se rechaza después de 30 segundos
        var timerId = setTimeout(reject.bind(null, 'Tiempo de espera agotado esperando la selección del archivo'), 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();

        // Las opciones de transferMethod son 'binario' y 'ascii'
         fileTransfer.setTransferOptions({transferMethod: 'ascii'});

         var localFile = yield promptForFileToUpload();

         // Recuperar el catálogo actual y añadirle el nombre de archivo seleccionado
         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);
    }
});

// Run the macro
return macro();