Etiqueta

26 noviembre 2020

03 julio 2020

Nuevo asistente para la construcción de aplicaciones finales (Deployment Tool)

La última actualización de Omnis 10.1 incluye una nueva herramienta denominada "Deployment Tool", la cual permite crear y personalizar nuestra aplicación final, es decir, la aplicación resultante de la integración de nuestras librerías y ficheros adicionales con el código Omnis (runtime), disponible tanto para Mac OS como para Windows. En el caso de macOS, la herramienta permite crear un paquete (bundle), mientras que en caso de Windows se permite la creación de un constructor completo o parcial. Además, (sólo para Windows) se incluye un nuevo componente externo, denominado "RCEdit", mediante el cual es posible modificar recursos del propio programa Omnis (runtime), permitiendo su completa personalización o "configuración de identidad" del producto final.

Opciones macOS


En caso de macOS y desde la primera pantalla de opciones que mostrará el asistente, podremos cambiar el nombre de la aplicación, la versión, el identificador, el fabricante, el aviso de copyright y su icono:



Desde la segunda pantalla podremos indicar la localización de nuestras carpetas "startup", grupos de iconos (los "iconsets" que requieran nuestras librerías), la "xcomp" e "icons", así como una opción para pre-serializar el paquete o agregar un carpeta de lectura/escritura personalizada.


Finalmente y desde la pantalla de opciones "Build", crearemos el "Omnis Bundle" (Omnis Runtime + nuestros ficheros), indicando una carpeta, es decir, la ruta a la carpeta donde quedará construida la aplicación final, junto con la versión de nuestro "Bundle". También podremos (si así lo deseamos) seleccionar la opción que nos permitirá borrar la carpeta resultante o "Bundle" en caso de producirse algún error durante el proceso.

Opciones Windows

En caso de Windows, podremos indicar el nombre de la aplicación, fabricante, versión, aviso de derechos de autor, nombre del ejecutable y la ruta hacia el archivo ".ico", que será usado en sustitución del icono propio de Omnis.


Desde la segunda pantalla (como en el caso de macOS) podremos especificar su "startup", "iconsets", "xcomp" e "icons", así como la opción para pre-serializar el paquete o agregar un directorio de lectura/escritura personalizado.


En la pantalla de opciones "Build", podremos especificar la ubicación de los archivos de solo lectura propios de Omnis (es decir nuestro Omnis Studio Runtime xx.x), así como la ubicación de los archivos de lectura/escritura (es decir los que se ubicarán en "AppData"), finalmente especificaremos la ruta hacia la carpeta de salida (donde quedará construida la aplicación final) y la opción para 32 o 64 bits. También en éste caso, podremos optar por indicar si queremos que se borre la carpeta "Bundle", si se produce algún error durante el proceso.


En caso de Windows, también podremos optar por crear un directorio simple "Flat tree", una división en árbol "Split tree" o una división en árbol con inclusión del instalador inicial "Split tree with firstruninstall".

  • La opción "Flat tree" generará una carpeta simple con todos los archivos, los de lectura y los de lectura/escritura.
  • La opción "Split tree" generará una carpeta con los archivos de solo lectura, es decir aquellos cuyo destino será "Program Files" y otra de lectura/escritura con los destinados a "AppData".
  • La opción "Split Tree with firstruninstall" generará una carpeta con los archivos de solo lectura y dentro de esta,  otra adicional denominada "firstruninstall", con los archivos de lectura/escritura que Omnis copiará automáticamente sobre la carpeta "AppData" del usuario, la primera vez que ejecute la aplicación.

Es interesante hacer notar que la opción "firstruninstall" nos permitirá instalar y configurar nuestra aplicación sin la necesidad de construir un instalador, lo cual puede resultar ser más rápido, sencillo y/o más conveniente para nuestro producto final. Podríamos incluso usar la función "7Zip's SFX" para que simplemente se auto-descomprima, simplificando así enormemente la instalación de nuestra aplicación, ya que no precisaría del uso de complejos instaladores.

Uso del editor de recursos "RCEdit"


El nuevo componente externo denominado "RCEdit" nos permite editar varios recursos de Windows, tales como la versión del producto, el texto de la versión y el icono representativo del ejecutable Omnis. El componente externo implementa varios métodos nuevos, que podrán ser invocados desde nuestro código Omnis.

  • $setapplicationmanifest(cFile, cManifest), cambia el manifiesto incluido cManifest según la ruta indicada por cFile), ejemplo: Do rcedit.$setapplicationmanifest(“C:\omnis.exe”, “C:\folder\newManifest.xml”) Returns #F

  • $setresourcestring(cFile, cResource, cValue), cambia el recurso "cResource" por el valor de "cValue" para según la ruta indicada en "cFile", ejemplo: Do rcedit.$setresourcestring(“C:\omnis.exe”, “1”, “Nuevo valor”) Returns #F

  • $setproductversion(cFile, cProductVersion), cambia el recurso del ejecutable Windows "Product Version" según lo indicado en cProductVersion para la ruta del archivo cFile, ejemplo: Do rcedit.$setproductversion(“C:\omnis.exe”, “10.1”)

  • $seticon(cFile, cIcon), cambia el icono del ejecutable Windows indicado la ruta del archivo cFile, por el archivo ".ico", indicado en la ruta cIcon, ejemplo: Do rcedit.$seticon(“C:\omnis.exe”, “C:\newIcon.ico”) Returns #F

  • $setversionstring(cFile, cVersion, cValue), cambia el texto de versión en "cVersion" por el especificado en "cValue" según la ruta indicada en cFile, ejemplo: Do rcedit.$setversionstring(“C:\omnis.exe”, “Comments”, “Comment version string”) Returns #F

  • $setfileversion(cFile, cFileVersion), cambia el recurso del ejecutable Windows "File Version" por el contenido en cFileVersion, ejemplo: Do rcedit.$setfileversion(“C:\omnis.exe”, “10.1.0.0”) Returns #F

13 febrero 2020

Cómo mostrar un PDF desde un campo BLOB de Oracle sobre el navegador, sin descargarlo

En este artículo quiero mostrarles un "truco" ideado por Francesco Del Dotto de soporte Omnis en Italia, de modo que lo primero es agradecer su tiempo y darle mi enhorabuena ante la pericia demostrada.


En principio podría pensarse que se trata de algo sencillo de hacer desde Omnis Studio, ya conocemos el método Do $cinst.$clientcommand("assignpdf",row) donde el parámetro row se define como row(html-object-name,pdf-parameters,pdf-id,timeout,pdf-filename), pero el reto está precisamente en el parámetro pdf-filename, es decir que el uso de éste método requiere de la presencia física del fichero con el documento pdf, pero el reto que se plantea en el enunciado de este artículo, es enviar al navegador del cliente, un documento pdf que se encuentra en una variable binary y no en un fichero físico.

La parte digamos "sencilla" fue construir el método (denominado muestraPdf) javascript que se encargaría de mostrar el documento, pasándole el contenido del campo BLOB de oracle y que mostramos a continuación:

# El dato BLOB de Oracle es iDocumentos.DOCUMENTO
# pdfBuffer es una variable var de JavaScript
# el método ha sido marcado como "Execute On Client" 

Calculate pdfBuffer as iDocumentos.DOCUMENTO
JavaScript: var arrayBuffer = base64ToArrayBuffer(pdfBuffer);
JavaScript: function base64ToArrayBuffer(base64) {
JavaScript: var binaryString = window.atob(base64);
JavaScript: var binaryLen = binaryString.length;
JavaScript: var bytes = new Uint8Array(binaryLen);
JavaScript: for (var i = 0; i < binaryLen; i++) {
JavaScript: var ascii = binaryString.charCodeAt(i);
JavaScript: bytes[i] = ascii;
JavaScript: }
JavaScript: return bytes;
JavaScript: }
JavaScript: var blob = new Blob([arrayBuffer], {type: "application/pdf"});
JavaScript: var link = window.URL.createObjectURL(blob);
JavaScript: window.open(link);

El problema estriba en como invocar a éste método desde el lado del servidor, ya que sólo existe en el navegador del cliente y por tanto sólo puede ser invocado desde un método que (al igual que este) haya sido marcado como "Execute On Client", el problema es que la recuperación del campo BLOB con el contenido del PDF, debe hacerse desde un método creado y ejecutado en el entorno del servidor, es decir que no puede llevar la marca "Execute On Client", y es aquí donde llega el "truco de Francesco".

Para que la magia tenga su efecto, lo primero que hacemos es colocar un "Timer Control" sobre el formulario remoto...


...al que incluiremos en su método "$event" el código siguiente y que estratégicamente habremos marcado como "Execute On Client":

On evTimer
Do $cinst.$objs.timerObj.$running.$assign(kFalse)
Do $cinst.$muestraPdf()

El truco consiste en activar el timer alojado en el navegador del cliente desde el servidor, el cual se encargará a su vez de invocar al método "$muestraPdf()" ademas de auto-desactivarse.

A continuación mostramos la secuencia que obtiene el campo BLOB de oracle y activa el timer:

Calculate lCompara as con("where ROWID = '";iListaDctos.ROWID;"'")
Do iDocumentos.$select(lComparaReturns #F
If flag true
Do iDocumentos.$fetch()
If not(isclear(iDocumentos.DOCUMENTO))
Do $cinst.$objs.timerObj.$running.$assign(kTrue)
End If
End If

El código encargado de recuperar el documento desde la base de datos, es también el encargado de activar el timer, que fue previamente alojado en el navegador del cliente.

Gracias de nuevo a Francesco de soporte Omnis, por este maravilloso truco.
 

22 enero 2020

La librería de conversión de DML a SQLite

Recientemente Omnis Studio proporciona la utilidad denominada "Convert Datafile to RDBMS", la cual está soportada por la librería "omsqlconv.lbs" bajo el directorio "startup", pero no debemos pasar por alto, que ésta, no sólo se encarga del proceso de conversión, sino que también funciona en segundo plano, realizando el trabajo de emular los antiguos comandos DML, traduciéndolos y ejecutándolos contra SQLite, así como del comportamiento de semáforos (semaphores) y bloques reversibles (reversible blocks) cuando son usados.


La librería "omsqlconv.lbs", se apoya también en tablas creadas sobre la base de datos resultante de la conversión, las cuales no deberán ser modificadas o eliminadas, a continuación mostramos una lista de los comandos DML que son emulados:

Close datafile, Close lookup file, Create datafile, Floating default datafile, Open datafile, Open lookup file, Prompt for datafile, Set current datafile, Set default datafile, lookup(), Build indexes, Delete data, Drop indexes, Open runtime datafile browser, Rename data, Cancel prepare for update, Delete, Delete with confirmation, Do not flush data, Do not wait for semaphores, Flush data, Flush data now, Prepare for edit, Prepare for insert, Prepare for insert with current values, Test for only one user, Update files, Update files if flag set, Wait for semaphores, Clear all files, Clear main & connected, Clear main file, Clear range of fields, Clear selected files, Set main file, Clear find table, Disable relational finds, Enable relational finds, Find, Find first, Find last, Load connected records, Next, Previous, Prompted find, Single file find, Test for a current record, Test for a unique index value, Clear search class, Reinitialize search class, Set search as calculation, Set search name, Test data with search class, Clear sort fields, Set sort field, Build list from file, Begin reversible block, End reversible block, Quit all methods, $root.$getodbfilelist(), y alguna funciones de sys(), como: sys(11), sys(139), sys(3000) & sys(3001)

Para habilitar la emulación de comandos DML, es necesario establecer la preferencia de librería "$mapdmltodam" para SQLite. No obstante aún habrá que hacer un pequeño cambio en el código de nuestra librería, que tiene que ver con el modo en que se abrimos o accedemos a la base de datos, antes un fichero con extensión .df1 y ahora con extensión .db. El comando para SQLite sería:

Open datafile sdb://192.168.0.10:5743/SQLiteTest

Pero si queremos también podemos optar por cambiar éste comando y hacer uso de la sintaxis de notación del modo siguiente:

Do omsqlSess.$logon(‘sdb://192.168.0.10:5743/SQLiteTest’,’’,’’) Returns #F