<?xml version="1.0" encoding="UTF-8" standalone="no"?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"><channel><title>Blog de Aula Omnis Studio</title><description>La intención de este blog es recoger las experiencias de un desarrollador de aplicaciones con Omnis Studio.</description><managingEditor>noreply@blogger.com (Aula Omnis Studio)</managingEditor><pubDate>Thu, 4 Jun 2026 11:38:19 +0200</pubDate><generator>Blogger http://www.blogger.com</generator><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">231</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">25</openSearch:itemsPerPage><xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" content="noindex" name="robots"/><link>http://framosmu.blogspot.com/</link><language>en-us</language><itunes:explicit>no</itunes:explicit><itunes:subtitle>La intención de este blog es recoger las experiencias de un desarrollador de aplicaciones con Omnis Studio.</itunes:subtitle><itunes:owner><itunes:email>noreply@blogger.com</itunes:email></itunes:owner><item><title>Ejemplo HTTP Worker para IA</title><link>http://framosmu.blogspot.com/2025/02/ejemplo-http-worker-para-ia.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><category>Aula Omnis</category><category>jsClient</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Wed, 19 Feb 2025 11:49:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-6485548874798973007</guid><description>&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: Helvetica;"&gt;La última versión de Omnis recientemente liberada (Omnis Studio 11.2 Revision 39462) nos muestra como acceder a los modelos de IA haciendo uso de sus API’s mediante el objeto &lt;b&gt;HTTP Worker&lt;/b&gt; de Omnis. Se ha agregado una aplicación-ejemplo llamada HTTP AI a la sección “&lt;b&gt;Samples&lt;/b&gt;” del “&lt;b&gt;Hub&lt;/b&gt;” en el navegador de Studio para demostrar cómo acceder a varios modelos de IA. Naturalmente, primero deberemos disponer de una clave&amp;nbsp;&lt;b&gt;API&lt;/b&gt; del proveedor de IA correspondiente, para así, poder hacer uso de su servicio, pero, para empezar seguramente lo mejor es solicitar una clave o “&lt;b&gt;key&lt;/b&gt;” gratuita de demostración.&lt;/span&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIiMF_v4_WXi-A8Sec54OeQJPlKmyXS6aHAWD_KaHN_p_q7s-tbhNy8PtkKBwrKra1jAcBsGacTyvG3uQZkIcjXIK2gGI0fHfgJdm_HYgtggke99eOlIjNjeV_A_hvvYUd_FVo4WSPxxtI8E7Q4-IviuZreUY7PHDPnGHmPW11Ozx0U1aZin2J/s1646/Captura%20de%20pantalla%202025-02-19%20a%20las%2011.39.53.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1514" data-original-width="1646" height="413" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIiMF_v4_WXi-A8Sec54OeQJPlKmyXS6aHAWD_KaHN_p_q7s-tbhNy8PtkKBwrKra1jAcBsGacTyvG3uQZkIcjXIK2gGI0fHfgJdm_HYgtggke99eOlIjNjeV_A_hvvYUd_FVo4WSPxxtI8E7Q4-IviuZreUY7PHDPnGHmPW11Ozx0U1aZin2J/w552-h413/Captura%20de%20pantalla%202025-02-19%20a%20las%2011.39.53.png" width="552" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class="p1" style="font-family: Helvetica; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: justify;"&gt;En el ejemplo, Omnis utiliza un objeto HTTP Worker para realizar llamadas &lt;b&gt;RESTful&lt;/b&gt; a la API del servicio de IA correspondiente. Se proporcionan clases-objeto para realizar llamadas a &lt;b&gt;Gemini&lt;/b&gt;, &lt;b&gt;OpenAI&lt;/b&gt; y &lt;b&gt;Anthropic&lt;/b&gt; de Google, que heredan el objeto HTTP Worker; también se incluye compatibilidad con &lt;b&gt;AI Vision&lt;/b&gt;, que permite analizar e interpretar imagenes. Desde cada una de estas clases-objeto, se invoca al método denominado “&lt;b&gt;$runprompt&lt;/b&gt;” el cual se encarga de generar la solicitud en formato JSON y de realizar la llamada RESTful. Al finalizar, se invoca al método “&lt;b&gt;$completed&lt;/b&gt;” el cual se encarga de pasar los resultados al método “&lt;b&gt;$ai_completed&lt;/b&gt;” o al “&lt;b&gt;$ai_error&lt;/b&gt;” (si se ha producido un error) correspondientes a la instancia de ventana que se encargo de invocar a la API. Se proporciona una clase-objeto adicional denominada “&lt;b&gt;oAIFunctions&lt;/b&gt;” donde es posible agregar métodos con el prefijo “&lt;b&gt;$ai_&lt;/b&gt;” para añadir (si así se desea) otras funciones, tal como se muestra en el ejemplo.&lt;/p&gt;&lt;p class="p2" style="font-family: Helvetica; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 22px;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class="p1" style="font-family: Helvetica; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: justify;"&gt;Las configuraciones de IA usadas en el ejemplo han sido agregadas al archivo de configuración “&lt;b&gt;userconfig.json&lt;/b&gt;” en un grupo específico denominado “&lt;b&gt;ai&lt;/b&gt;”, lo cual también permite incluir la clave API que se almacena en texto sin formato.&lt;/p&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIiMF_v4_WXi-A8Sec54OeQJPlKmyXS6aHAWD_KaHN_p_q7s-tbhNy8PtkKBwrKra1jAcBsGacTyvG3uQZkIcjXIK2gGI0fHfgJdm_HYgtggke99eOlIjNjeV_A_hvvYUd_FVo4WSPxxtI8E7Q4-IviuZreUY7PHDPnGHmPW11Ozx0U1aZin2J/s72-w552-h413-c/Captura%20de%20pantalla%202025-02-19%20a%20las%2011.39.53.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Nueva funcionalidad jsRemoteForm (history stack)</title><link>http://framosmu.blogspot.com/2025/01/nueva-funcionalidad-jsremoteform.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><category>Aula Omnis</category><category>jsClient</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Fri, 3 Jan 2025 12:39:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-4463149318688790153</guid><description>&lt;p&gt;&amp;nbsp;La última revisión de Omnis Studio 11.2, incorpora una (más que interesante) funcionalidad que añadir a nuestras aplicaciones Web, denominada "history stack".&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEMDHBsxNUm5PRv0OXpbicbtCLDZRw2Ez9kmYacQRKIoecjh4GgUrP-lEaf_qQY34ScvNtWfKW6tm0K-GMs9vSUStk5xC4L6-bVf8Ha9vA7gFyHRx26r5lDEhPTf-6KDDwzafN2aUxlL1Xyo72N8zbOuIpXko9GzIl1_r_WALDOI3OCxBSqVCL/s724/Captura%20de%20pantalla%202025-01-03%20a%20las%2011.57.26.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="108" data-original-width="724" height="48" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEMDHBsxNUm5PRv0OXpbicbtCLDZRw2Ez9kmYacQRKIoecjh4GgUrP-lEaf_qQY34ScvNtWfKW6tm0K-GMs9vSUStk5xC4L6-bVf8Ha9vA7gFyHRx26r5lDEhPTf-6KDDwzafN2aUxlL1Xyo72N8zbOuIpXko9GzIl1_r_WALDOI3OCxBSqVCL/s320/Captura%20de%20pantalla%202025-01-03%20a%20las%2011.57.26.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;El "history stack"&amp;nbsp;puede estar formado por la lista de páginas que visitamos o por los estados entre los que navega un usuario durante el transcurso de una sesión abierta desde el navegador. Los estados en dicho historial pueden ser agregados o reemplazados, pero nunca eliminados.&lt;/p&gt;&lt;p&gt;Sin embargo, al agregarse un nuevo estado, se invalidan los estados que estén por delante de la posición actual del usuario. El historial persiste durante el tiempo que dure la sesión con el usuario, aún en el caso de que éste refresque&amp;nbsp;la página.&lt;/p&gt;&lt;p&gt;Una nueva aplicación de muestra incluida en el "HUB" denominada "JS History" nos enseña cómo es posible hacer uso de las flechas de dirección del navegador web (ver imagen superior) para moverse entre las diferentes pestañas del formulario"jsRemoteForm".&lt;/p&gt;&lt;p&gt;El comportamiento habitual de los botones del navegador puede ser cambiado mediante un nuevo método en los "jsRemoteForm" denominado "$pushhistorystate()", el cual puede ser ejecutado desde un método de tipo cliente o bien de servidor.&lt;/p&gt;&lt;p&gt;Cuando el usuario usa los botones "Atrás" o "Adelante" del navegador para moverse por el historial, lo que sucederá es que se invocará un método de devolución de llamada denominado "$applynewhistory", que a su vez recibirá el valor de "$pushhistorystate" como parámetro.&lt;/p&gt;&lt;p&gt;Gracias a ésta nueva funcionalidad nuestras aplicaciones Web se verán aún mas integradas en la ventana de navegación del cliente Web, mejorando su experiencia de uso.&lt;/p&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEMDHBsxNUm5PRv0OXpbicbtCLDZRw2Ez9kmYacQRKIoecjh4GgUrP-lEaf_qQY34ScvNtWfKW6tm0K-GMs9vSUStk5xC4L6-bVf8Ha9vA7gFyHRx26r5lDEhPTf-6KDDwzafN2aUxlL1Xyo72N8zbOuIpXko9GzIl1_r_WALDOI3OCxBSqVCL/s72-c/Captura%20de%20pantalla%202025-01-03%20a%20las%2011.57.26.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><georss:featurename xmlns:georss="http://www.georss.org/georss">Salamanca, España</georss:featurename><georss:point xmlns:georss="http://www.georss.org/georss">40.9701039 -5.6635396999999994</georss:point><georss:box xmlns:georss="http://www.georss.org/georss">13.773327584715297 -40.8197897 68.166880215284692 29.4927103</georss:box></item><item><title>Campos PDF editables con Omnis Studio 11.2</title><link>http://framosmu.blogspot.com/2024/08/campos-pdf-editables-con-omnis-studio.html</link><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Thu, 29 Aug 2024 13:10:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-7028515792552789454</guid><description>&lt;p&gt;Una de las novedades que nos trae Omnis Studio 11.2 es la capacidad para colocar campos editables en nuestros informes PDF.&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIrukshs7wjtC-gCzVAg_vMyGbK7wt80PW57xHDYE9AhAlDblgpNR53gCR6q1Ya7PzD98sEq2Dvd7lH2DpQkzJZsf1Zjli8PZkkOs_TEDcCzjsLcHd-3si5ueQUfpPRTI0AxovjGmwwJNJsPq4vuYKLwdksscD3IkugbMPX1khWmv7qbu7UjCa/s480/hqdefault.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="360" data-original-width="480" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIrukshs7wjtC-gCzVAg_vMyGbK7wt80PW57xHDYE9AhAlDblgpNR53gCR6q1Ya7PzD98sEq2Dvd7lH2DpQkzJZsf1Zjli8PZkkOs_TEDcCzjsLcHd-3si5ueQUfpPRTI0AxovjGmwwJNJsPq4vuYKLwdksscD3IkugbMPX1khWmv7qbu7UjCa/s320/hqdefault.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Ahora los campos de entrada de informes tienen una nueva propiedad, &lt;b&gt;$enterable&lt;/b&gt;, que permite al usuario final ingresar y guardar texto en un informe en formato PDF. (Revisión 38452, ST/EC/1849)&lt;/p&gt;&lt;p&gt;La activación de la mencionada propiedad permitirá que el usuario final ingrese y guarde texto en un campo de un informe PDF configurando su propiedad $enterable en kTrue. Cuando el usuario final abra el informe PDF generado, el campo estará activo y se podrá ingresar texto, tras lo que podrá guardar el PDF con el nuevo contenido.&lt;/p&gt;&lt;p&gt;Sólo se aplica a archivos PDF generados mediante &lt;b&gt;Omnis PDF Device&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Tenga en cuenta que si el campo editable del informe está vacío cuando se imprime y la propiedad &lt;b&gt;$nolineifempty&lt;/b&gt; es kTrue, entonces toda la línea que incluye el campo editable no será incluida en el informe. En este caso, es recomendable fijar la propiedad $nolineifempty para los campos editables del informe en kFalse (que es el valor predeterminado).&lt;/p&gt;&lt;p&gt;&lt;b&gt;PRIobjectStruct&lt;/b&gt; también se ha actualizado con un nuevo miembro &lt;b&gt;mEnterable,&lt;/b&gt;&amp;nbsp;con el fin de que los desarrolladores de componentes externos puedan crear sus propios campos editables.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIrukshs7wjtC-gCzVAg_vMyGbK7wt80PW57xHDYE9AhAlDblgpNR53gCR6q1Ya7PzD98sEq2Dvd7lH2DpQkzJZsf1Zjli8PZkkOs_TEDcCzjsLcHd-3si5ueQUfpPRTI0AxovjGmwwJNJsPq4vuYKLwdksscD3IkugbMPX1khWmv7qbu7UjCa/s72-c/hqdefault.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Uso del método $showurl y $closeurl()</title><link>http://framosmu.blogspot.com/2024/04/uso-del-metodo-showurl-y-closeurl.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Sun, 28 Apr 2024 11:23:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-7209833427160907308</guid><description>&lt;p&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi__4Nefb2AOpqzMHff-F8xoMvyEF_gcaO-BfPng-Db6IR6rSdmsjWgZR9_Qm7bPOCS-W1IxLK8cHgUYtUUsP6gJjuctO2b-me987k2Cpm5oFr7KvwPGoDz2AjtvUsrSbH8n2izkZSLxLat-yJa2D43woy2RLztxn7QLHtUL8_CJNqa4cCjz8aM/s1920/imgscursoweb-01_xl.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1120" data-original-width="1920" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi__4Nefb2AOpqzMHff-F8xoMvyEF_gcaO-BfPng-Db6IR6rSdmsjWgZR9_Qm7bPOCS-W1IxLK8cHgUYtUUsP6gJjuctO2b-me987k2Cpm5oFr7KvwPGoDz2AjtvUsrSbH8n2izkZSLxLat-yJa2D43woy2RLztxn7QLHtUL8_CJNqa4cCjz8aM/s320/imgscursoweb-01_xl.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&amp;nbsp;La estructura de éstos métodos es la siguiente:&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;$showurl(cURL[,cFrame,cWindowProperties,cWindowRef])&lt;/b&gt;&amp;nbsp;abre la URL en una nueva ventana o marco en el cliente; cURL es la URL de la página HTML; cFrame es el nombre del marco HTML; si cFrame está vacío, la página se muestra en una nueva ventana; de lo contrario, se muestra en el marco especificado para la ventana actual.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;$close(cWindowRef)&lt;/b&gt;&amp;nbsp;cierra la ventana del navegador que fue abierta previamente mediante el método $showurl(), consta de un solo parámetro y deberá ser el indicado mediante el cuarto parámetro del método $showurl() anterior.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;En este artículo hablare del método $showurl, sus alternativas de uso, su equivalente JavaScript y algunos ejemplos, empecemos por desgranar sus parámetros:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;cURL&lt;/b&gt;: Es la dirección de la página a presentar en una nueva ventana del cliente o bien sobre el marco especificado mediante el siguiente parámetro de la página HTML que figura actualmente en el cliente.&lt;/li&gt;&lt;li&gt;&lt;b&gt;cFrame&lt;/b&gt;: Es el nombre de marco HTML. Si cFrame está vacío, la página se mostrará&amp;nbsp; en una nueva ventana, de lo contrario se mostrará en el marco especificado para la ventana actual.&lt;/li&gt;&lt;li&gt;&lt;b&gt;cWindowProperties:&lt;/b&gt;&amp;nbsp;Será ignorado si cFrame no existe. De lo contrario, tiene el mismo formato que los argumento del método Javascript "window.open", por ejemplo, "&lt;b&gt;toolbar&lt;/b&gt; = 0, &lt;b&gt;menubar&lt;/b&gt; = 1" indicaría que la ventana del navegador tendrá una barra de menú, pero no una barra de herramientas.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;A continuación les muestro las posibles palabras clave o argumentos que podemos aportar en este tercer parámetro:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"&gt;&lt;div style="text-align: left;"&gt;&lt;div&gt;&lt;b&gt;toolbar&lt;/b&gt; - La ventana del navegador tendrá una barra de herramientas&lt;/div&gt;&lt;div&gt;&lt;b&gt;status&lt;/b&gt; - La ventana del navegador tendrá una barra de estado&lt;/div&gt;&lt;div&gt;&lt;b&gt;menubar&lt;/b&gt; - La ventana del navegador tendrá una barra de menú&lt;/div&gt;&lt;div&gt;&lt;b&gt;scrollbars&lt;/b&gt; - La ventana del navegador tendrá barras de desplazamiento&lt;/div&gt;&lt;div&gt;&lt;b&gt;resizable&lt;/b&gt; - La ventana del navegador es de tamaño variable&lt;/div&gt;&lt;div&gt;&lt;b&gt;location&lt;/b&gt; - La ventana del navegador tendrá una barra para direcciones&lt;/div&gt;&lt;div&gt;&lt;b&gt;directories&lt;/b&gt; - La ventana del navegador mostrará el directorio Web&lt;/div&gt;&lt;div&gt;&lt;b&gt;width&lt;/b&gt; - Anchura de la ventana del navegador&lt;/div&gt;&lt;div&gt;&lt;b&gt;height&lt;/b&gt; - Altura de la ventana del navegador&lt;/div&gt;&lt;div&gt;&lt;b&gt;top&lt;/b&gt;&amp;nbsp; - Coordenada superior de la ventana del navegador&lt;/div&gt;&lt;div&gt;&lt;b&gt;left&lt;/b&gt; - Coordenada izquierda de la ventana del navegador&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;Todas éstas palabras clave son boleanas (0 o 1) a excepción de la &lt;b&gt;width&lt;/b&gt;, &lt;b&gt;height&lt;/b&gt;, &lt;b&gt;top&lt;/b&gt; y &lt;b&gt;left&lt;/b&gt;, que deberán ser valores expresados en píxel's.&amp;nbsp;&lt;/p&gt;&lt;div&gt;Les mostraré ahora algunos ejemplos de uso:&lt;/div&gt;&lt;blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"&gt;&lt;div style="text-align: left;"&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;$cinst.$showurl(lvURL,,"toolbar=yes,location=no,width=750,height=400,resizable=yes,scrollbars=yes")&lt;/div&gt;&lt;div&gt;$cinst.$showurl("http://www.myserver.com/cgi-bin/omniscgi?OmnisServer=192.168.1.1&amp;amp;OmnisLibrary=MyLib&amp;amp;OmnisClass=rtLookup&amp;amp;Ukey=132456778","_blank")&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;Decir que también podremos usar una alternativa JavaScript inmersa en el mismo método:&lt;/p&gt;&lt;blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"&gt;$cinst.$showurl('javascript:self.close()','_top')&lt;br /&gt;$cinst.$showurl("javascript:document.write('Testing');","_blank")&lt;br /&gt;$cinst.$showurl(“javascript:self.close();window.open('http://127..0.0.1/insite/html/ejemplo.htm','orderpad','width=400,height=300,top=50,left=300,status=no,toolbar=no,menubar=no,scrollbars=yes’);”)&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"&gt;$cinst.$showurl("javascript:window.top.location.href=‘https://framosmu.blogspot.com/’")&amp;nbsp;&lt;/blockquote&gt;&lt;p&gt;De modo que podemos decir que el método &lt;b&gt;$showurl(cURL[,cFrame,cWindowProperties])&lt;/b&gt; es equivalente al método &lt;b&gt;javascript: window.open(URL,target,options)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;En éste caso&amp;nbsp;“&lt;b&gt;target&lt;/b&gt;” sería el equivalente a cFrame y puede tener los valores siguientes:&lt;/p&gt;&lt;blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"&gt;&lt;b&gt;"_self"&lt;/b&gt;&amp;nbsp;- Nueva página en la misma ventana&lt;br /&gt;&lt;b&gt;"_blank"&lt;/b&gt;&amp;nbsp;- Nueva página en otra ventana&lt;br /&gt;&lt;b&gt;"_parent"&lt;/b&gt;- Nueva página en la ventana padre&lt;br /&gt;&lt;b&gt;"_top"&lt;/b&gt;- Nueva página en la ventana superior&lt;br /&gt;&lt;b&gt;frame_name&amp;nbsp;&lt;/b&gt;- Nueva página en la ventana o marco denominado “frame_name”&lt;/blockquote&gt;&lt;p&gt;Un último ejemplo para abrir una ventana en otra pestaña del navegador sin hacer uso del método $showurl, sería:&lt;/p&gt;&lt;blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px;"&gt;&lt;p style="text-align: left;"&gt;JavaScript: window.open(lvURL,lvNewTabName,"titlebar=no,toolbar=no,location=no,status=no,menubar=no,resizable=yes,scrollbars=yes")&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Bueno, hacía mucho que no publicaba algo nuevo en éste blog, espero que les resulte útil, déjenme sus comentarios y/o aportaciones si lo consideran oportuno, nos vemos...&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi__4Nefb2AOpqzMHff-F8xoMvyEF_gcaO-BfPng-Db6IR6rSdmsjWgZR9_Qm7bPOCS-W1IxLK8cHgUYtUUsP6gJjuctO2b-me987k2Cpm5oFr7KvwPGoDz2AjtvUsrSbH8n2izkZSLxLat-yJa2D43woy2RLztxn7QLHtUL8_CJNqa4cCjz8aM/s72-c/imgscursoweb-01_xl.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Integración Paypal REST API con Omnis Studio</title><link>http://framosmu.blogspot.com/2024/04/integracion-paypal-rest-api-con-omnis.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Wed, 17 Apr 2024 11:18:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-6250538174330291833</guid><description>&lt;div style="text-align: justify;"&gt;Hacía tiempo que no publicaba algo nuevo en mi repositorio público de GitHub y ya iba siendo hora, pensando en que hacer, me he decidido por mostrar un breve ejemplo de cómo hacer uso en Omnis Studio de la API REST de PayPal en su entorno de pruebas SandBox con Omnis Studio. Podrán descargar la librería&amp;nbsp; desde el siguiente enlace:&amp;nbsp;&lt;a href="https://github.com/framosmu/Omnis_PayPal_REST_API"&gt;Github de Francisco Ramos&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEgLZ3B5GVIBi-wU2gnA7JInTYZ_2-TBdeGO2ieHBUbBrtcqeJYai02yNm8ZdDTjL_0nyiXI8dcBv6vC5TOSQPDX3iV19xGmWDIw4wbdeTVp7Kid_yHfBOfuKYV7jJmxfJDZCckgjXMFn419vUIifAaDhzTyl1_ccnzNNbWFJvgGq9Wj3MhrAtvL" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="222" data-original-width="1260" height="102" src="https://blogger.googleusercontent.com/img/a/AVvXsEgLZ3B5GVIBi-wU2gnA7JInTYZ_2-TBdeGO2ieHBUbBrtcqeJYai02yNm8ZdDTjL_0nyiXI8dcBv6vC5TOSQPDX3iV19xGmWDIw4wbdeTVp7Kid_yHfBOfuKYV7jJmxfJDZCckgjXMFn419vUIifAaDhzTyl1_ccnzNNbWFJvgGq9Wj3MhrAtvL=w585-h102" width="585" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/a/AVvXsEgLZ3B5GVIBi-wU2gnA7JInTYZ_2-TBdeGO2ieHBUbBrtcqeJYai02yNm8ZdDTjL_0nyiXI8dcBv6vC5TOSQPDX3iV19xGmWDIw4wbdeTVp7Kid_yHfBOfuKYV7jJmxfJDZCckgjXMFn419vUIifAaDhzTyl1_ccnzNNbWFJvgGq9Wj3MhrAtvL=s72-w585-h102-c" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Omnis Studio 11, soporte para TOTP</title><link>http://framosmu.blogspot.com/2023/06/omnis-studio-11-soporte-para-totp.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Tue, 6 Jun 2023 19:23:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-1739671285340380494</guid><description>La última actualización de Omnis Studio da soporte a TOTP, es el acrónimo de
"Time-based One Time Passwords", o contraseñas temporales de un solo uso. Es
decir, estas contraseñas tienen una vida útil bien de un uso, o de un periodo de
tiempo concreto a partir del cual se auto-destruyen. Dos nuevas funciones nos
permiten incorporar éste protocolo en nuestros desarrollos: &lt;b&gt;OW3.$totpgenerate()&lt;/b&gt;
y &lt;b&gt;OW3.$totpvalidate()&lt;/b&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;div style="text-align: center;"&gt;&lt;img alt="Tech Insight: Autenticación - TOTP | Citrix Tech Zone" class="rg_i Q4LuWd" data-atf="true" data-deferred="1" data-iml="683" height="169" jsname="Q4LuWd" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHCBURFBgVFBMZFRQYHBscHBoYExgbGhsdGBkcGxgUGBgcJC0kGx0pHhkYJzcpKS4wNTU0GiM5TDkyPi0yNDABCwsLEA8QGhERHj4jJCk4MDI+MDA+Ozc1OzUyMjIyPjQ0Ozs2MjYyNTI7MjI+MjYwNjI+MjIwOzIyNTQyMjIyO//AABEIAKgBLAMBIgACEQEDEQH/xAAbAAEAAwEBAQEAAAAAAAAAAAAAAwQFAQIGB//EADsQAAICAAUCBAYAAwYFBQAAAAECABEDEiExQQRRBRMiUjJCYXGBkSOh0QYVYpKx8RQzU3LwNERUs8H/xAAXAQEBAQEAAAAAAAAAAAAAAAAAAQMC/8QAIREBAQEAAQUBAQADAAAAAAAAABEBAgMSITFRQaEicYH/2gAMAwEAAhEDEQA/AP2aIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAnCJ2IHnKO0ZR2nqICIiAiIgIiICIiAiIgIiICIiByZ/iHiHklR5TvmIUFSlWdl9TDt9poSn13Sebk9VZXVtrur9P033l4y+XPOze32iHimGAxdhh5Tl9TLd0GrQnXXaSJ4lhEMRiqQtZqYGs3w/s6CVv7q/iF8/zs1ZfdhhKu+Ku/xKx8C9AAxNQmCoOQ1eCWOYgMDRzbAgjvNJw+sO7q56ytTG61VwmxR61VWbQ75QTQPfSpGniuCyZvMWgQD6gaJF5fvUr/3QDhMhNMyuuYZgvru2yFjZ9R3NyEeDPqfOAYlbrDZVKorAKQrg36rsEbDSpMzh9XeXUuTPz+tNeuwyQA6ksLFEG1NkH7UD+p5/vLCylvMXKCBeYbnYfmZyeBkBV8ylVMjZVKlxkZdTmogFrGlit5zD8EZQCMRc6spDeWxByoyAMGc3ox2IqWcPqd3V+Lq+Jr5IxiDlOgAokktlUDgkmv3POF4stsMQHBKZSQ5XZyQpBUkUSCN9xPP91/wBg59VIIYLsyvnBy33rS5E3hDMS2JiBnLYZtUygLhPmCgFjuSdb52knDyu71fEz8/q7/eWFlVvMXK10cwo0aP6O/aPEet8hM5RnA3y5dB3OYj+UzcXwG9sRbvFsMjEFcV8+WldTptvR7S91XhyujopKlxqSWYCuyk0PsKicLh3dTc25Nnj/Yniai/MHlUFJzsmmYkAHKxr4f5/eSYfieC3w4qmlLGmGijdj2qV+p8KzuXzVZwTWW/+S5fe+br6VzIMTwK1Kl9D5/y/9ds3fjb6/SWcN96nd1c/K0R1qFGdWDBQSa+guvvX+sq9N40jglgcKgpp8uocEqQVJuwp030nrpvDiqOrMpZ7tlVhutAkMzEn8iQnwbLhqmGwQgrmYKfXlXL6srBub34kzOHpd3qeNzP+Lw6/DsDOuozDUfDROb7UCfwZweI4VX5i1RbU16QQC2vFkfsTPwvBCmQB1pUyH+GfWMpUBxmpls3VXxc8nwC1VWxLCk2MpooxU+SLYkLaruTzLOH1O/qz00sXxDCS82Ioo0bI3y5q/wApB+0N4hhA0cRQQM3xD4avN9q5mdheCsiplxgcRc1s2HYYOANVDCiAqgG+PrOjwIBGQPuuEoJWyPJ+EnXWzWmkk4fTu6vxf6Drlx8+XUK2W7sH0q1j/NX4l2UPDujbCzlnDM7ZiQuUAlVWgLPt78y/OOUvj024d0/y9uxESOyIiAiIgIiICIiAiIgIiICIiAmb13h3msDmy6VYHqWjYKNfpJOh0NgVpNKIGOvhDa31OITwcx0Nqbq6OzDbZq4ng+DPrXU4gFiqJ0Wvg375Te+hGtzbiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgckWMTpRqyBtclkeJx9xzX+/2jE1zXcsK3247Xf85WwutRzlXHw2YjZWUm97oHtM3H/tFht1L9GqO2KuGzs6hThoAvzNmsNbKMtX6hxrJvLUL0hCgHOuwH/QxJSNbK3cb+3jtvOZW7jn5eeDvJogiLK3uHHy/vnmMre4c/L+ueJzExlUqCaLnKu+pCs1f5VY/iTSUiKm7jj5f3zK/VdUMKszasSFUKSzaaKoGpMuzM6cX1OKSLKqiqeykWaH1a7/7RFI84XiIJCsWQnQF8MqC16gG6vcVNDK3cb+3jtvKXUEFMRHGtM3qOhW7zKf8ADY+xA7gmfw5y2EhbcqLvnTeKRLlb3Db289952m7jj5f2N5LI2xFG7AfciUjlN3HPy/rmMre4cfL++eZIDc7BEDWN2A33H654nM3+Nduw35O8zvEWp2oLmKpq5CqAGewXIOW+KBP+ojdzkQhdaIYquHTFdCwLDUHcVwYI1xZ1DAi+3Ha7jBJKgncgcVx24+0r+G/C3HqHAHyLeg0/Us4Pwr9hzfHfn7wfqWIiRSIiAiIgIiICIiAiIgIiICIiAiJldT4l6zh4CebijRtaTD0u8V9aNV6QCxsaVqAt9X1aYKF3YKooWeSdAoG5JOgA1J0ma4xeqrNm6fBJ0WyMZxrRLKf4Kka0DmoiyhtZZ6Tw2mGJit5uNwxFKt7rhYdkIPrZY8sal7F4Ouh4/pzLib6UeobC6bDC5MqUQFRRoKLNQH5On37mUsFulw2zhqK+rVKC0hHtGWhYO2uh10mu2Ip3UnTlGOjaVt+xPORLPoFk0f4Z1rua1H1jyXE2FiB1DKbDAEH6HUbySQDFUDQEADQBG22AAr+U9eaOx3r4W/pt9dpIXFLr/ClxnRySCjZjTuLGR1oAEAG3Bv6fWaKitJF5w7Ha/gb/AErf6bzpxR2bcD4W5/G314jyXEsz+vwVzK/mDCcekMSKIOuQg7jmWvOHY8/K3G/H+8i6hUcUwah2Vh8Sle3Zj9omlxXPQ4j0MXEBQG8qrV/dibA+gmiBWg0Ey8Pw3BRw6qwYG9mokA2Tp9d+e+pmh547Ntfwt/Tf6SzS4mmf1vhaYzBmJBArRUOxJ+ZSeZb80djvXwt/Tb67Tnnjsdr+Bv6b/TeSaXHcHDCqqjZQANuBXGn6ksi80djvXwnn8bfWc84dm5+RuPx/vKXGZ1XiOErsHDqV9OYFlVsq5zWU6gZtSdBe843iPTjUu9C7/iYnBo6Zr7fv6GtXzR2PHynnbj99pT6brc2JiqQaQqF9DXqgY3p3JrvE0uHhfV4eIG8sNoQWzWdWFj1G82gGxNaS5gfCv2GwrjtxOeaOx4+RuduP9p6wQcou9hubO3J5MFupYiJFIiICIiAiIgIiICIiAkbuFBJIAGpJ2AHJkkyOv60FhhoMzZlJ+lOCFHdjX41J2MC/g9SrkgH1DcEEEXsaOtfWc6rqkwlLOwVRyTydAB3JOgA1JlPEwXUtiphDzMjUrYlZ3OoUsAQi2OAbLXWmtfwbDXFY4mI5xOpTRldcnkkj4UwrPlg6+q2LD5mFQPdY3U75unwO22Pifcj/AJK1eg9ZsaoQQdLpunTCUIihEGwAof73LEQEREBERAREQERECLFTMrLZFgixuLFWPrM4+HYp/wDcsLvRU0s5tRbGh6hp9PtWtEDKxfD3bELjHZFLA5VGpAUKVJJPIsEAbne5xOgxQVJ6ljRUtS1mq8y70ASRxYoC6mtEBERAREQEzOhYef1GvzYf/wBYmnMfw/8As/g9P1PUdThrWL1GTP2GQV6RxZ1PcwNiIiAiIgIiICIiAiIgIiICIiBn4Xi2C9ViAWaF6d+/2Mr9Ni4GGzEYmpY6sdPWwtVO1ZqHf4Re00f+HTQ5FsVXpGlaCu1Wf3I26DCO+EholtUX4ju22+g1gRjxTCJADhiSRQ1oqpY320U79pTxz0/UlWTFyYygFHQgOA9EAg/GjCjlYEHQ1YBGj/wWHYby0zC6ORbGYU1GuRoe8L0OGCCMNQQ2YEKB6srJm05ysw/JgVOn8QZGGF1AC4jaK635eIeyk/A3+Bje9FqJmrIeowExFKOodGFFWAII7EGZg83pPfj9OP8AufGwx/NsZK+7ivnvQNmJD03UJiKHRw6MLDKQQR3BEmgIiICIiAiIgIiICIiAiIgIiIHlhYmX0Xhb4bhjiBgL0rF5FfNiMP5TWnzvg3R4idZ1mI3UF1c4dYZWlSkGXIbNenfTU6wPooiICIiAiIgIiICIiAiIgIiICIiAiIgIiIGTj+HsjHF6chHbV0a/LxD3YD4H4zqL2sMAAPXS+ILjEp6sPFQjPhsBnUHZhdhkPDrY0IuwQNOY/wDaLwkdXheX5hwnOi4qfGmb4sh4LDQ/Qy4m+ljq+tGE1MW76ZK1ul1o/Kf6zuF1BdQyjEKkUCDhfvffiZWN0+JhqiM74uIiIrOM6Z6LDM4Rx6jQ3sfFVSbBUZRnTqc3OXExsv4t7gjVwWz3qylWog5ewNaXoQRzPfln3tsfbzztuJW8MAp6DgZtnJLfCvxEkk/k7VNCCIfLPuPHt4/HMeWfeefbz+OJ4x+pVGRTu7FRtoQjPZ+lIf5SzIRD5Z97ce3j8cyt1XUjDIFs7tZCKASeNdNFHcn9y/Mzp/8A1OLdXlTLe+Wvl+mbNf4lIjHXMteYj4an05rRlBvdiB6ddL2/1mlkPuO98frbaUsdsiuj7EOwJsqwJJK/Rhe3OhHIE/ht+Ul75V/00giXyz722rj97bxkPuPHbj8cyaU+o8QwsI5cTFRGq6bEVTW10Ttof1BE3ln3tz7efxxHln3nj28fjmesPEDAFSCCAQQbBB2IPIkkEVHxFU02LlOposo0Og0rbQ1M/o8ZPNx/4oFlKOZNaRddt+JL15bOwWxapbZWYCmc0VSmN/cDTfgxu2IVT4gQtGxi2aNBzlXSwLo0dYpGlhkN6lfMLOxUjtVgbCesG8ou7oXdXtzWl/aQeG3kN75je/Ye7X9yfp/gWq2G11txfEH6miIkUiIgIiICIiAiIgIiICIiAiIgIiICRYnG+42F/vsJLIsUbULo3vUYms7xRMAsPOYLpYzKhWlNXbqQDb/znEx8FAFXqQii6A8oDbMaGXsb/Mt42Er0WwsxFVYU1Z4s6ETh6ZCf+SO15V2Aoc7USKlKk6QLRZWz5iSW01I9J2AGmWvxLMqp6R6cMjc0Mu5NnnfW5JmPtO9cf5t9v5wVT63wfBx3R3wkZka7bDVi3oZApJF167/AmgBWg0Ej8w+xtvp+t94zn2ncdued+IKmmf4jhIcrMzIwNKyg5hpZGgOlA7yz5h9puiascfn6j98SLEK4i2VzLQINrRDAgkG+xP75iFU8Lp0cgP1AxQD8NoFLan1KNzYOn0mxM5ehw1YMMKmW6NjStudj/wDnEtjFPtOwO688bwVNKfU9CmIczF7qvTjYiD9IwF67yfMex3r5f3vt/Oczn2tte6/rff8AlIV3DUKABdAACySdO5Op+5ksizn2neuP3vtOZz7Dz7ePzzKVldV1gDEP0zMASqsAGzBVzMSPlFmgNbJ0nk9Xh/8AxsQ77YYvTtrr/oabtNfMfaePbzvzx/5cZz7Tz7eNuef/ACoKp+F9TnUgYTYeWjRAAJcZjl50vcgS7g/Cu+w3FHbkd5zOfY3HK88b8TuCKUCqoAVd8bXB+pYiJFIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgU+s6FMYqXBOXNWvuFE/fapUPgODoKYALloNpRbMbFb8fbSa8QMpvBcIkHXTNpYo5jbEiqJP8uKOs6PBsLT4jRsajTUEgUKqxt/QVqRAREQEREBERAREQEREBERAREjVwdiDuPyDRH7gSREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAzfGOhbqMI4a4hw2LKcwzahWDFGyMrZSBRphv20OI/9k8TUr1mIrFg1q2IBpi4uIwAz6ZhiIpO9YYN2YiBf8C8IxcBmfEx2xCyouQs7KhQUWUs27btoLoba3vRED//Z" width="300" /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;La primera contiene 4 parámetros necesarios, más 2
opcionales y su sintaxis es la siguiente:
&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"&gt;&lt;div style="text-align: left;"&gt;&lt;b&gt;OW3.$totpgenerate&lt;/b&gt;(&lt;i&gt;xSharedSecretKey&lt;/i&gt;,&lt;i&gt;iTimeStep&lt;/i&gt;,&lt;i&gt;iDigits&lt;/i&gt;,&lt;i&gt;&amp;amp;iTOTP&lt;/i&gt;[,&lt;i&gt;&amp;amp;cErrorText,iHashType&lt;/i&gt;=kOW3hashSHA1])&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;Esta función genera una contraseña de un solo uso con base en el tiempo, quedará contenida en&amp;nbsp;&lt;i&gt;iTOTP&lt;/i&gt; y se utilizará para ello el algoritmo TOTP. Retornado "true" si la función es ejecutada con éxito.&lt;/p&gt;&lt;p&gt;Parámetros obligatorios:&lt;/p&gt;&lt;p&gt;&lt;i&gt;xSharedSecretKey&lt;/i&gt; (Binary) es la clave secreta compartida, su longitud debe estar entre 16 y 256 bytes.&lt;/p&gt;&lt;p&gt;&lt;i&gt;iTimeStep&lt;/i&gt; (Integer 32 bit) es el salto de tiempo en segundos el cual deberá estar entre 1 y 3600.&lt;/p&gt;&lt;p&gt;&lt;i&gt;iDigits&lt;/i&gt;&amp;nbsp;(Integer 32 bit) es el número de dígitos del TOTP resultante,&amp;nbsp;un valor entre 6 y 8.&lt;/p&gt;&lt;p&gt;&lt;i&gt;iTOTP&lt;/i&gt;&amp;nbsp;(Integer 32 bit) recibe el TOTP generado.&lt;/p&gt;&lt;p&gt;Parámetros opcionales:&lt;/p&gt;&lt;p&gt;&lt;i&gt;cErrorText&lt;/i&gt;&amp;nbsp;(Character 100000000) Si se proporciona, recibirá la descripción del posible error provocado por $totpgenerate o $totpvalidate (si resultó "false").&lt;/p&gt;&lt;p&gt;&lt;i&gt;iHashType&lt;/i&gt;&amp;nbsp;(Integer 32 bit), su valor por defecto es proporcionado por la constante kOW3hashSHA1) es el tipo de "hash" a utilizar, use una de las constantes del grupo kOW3hash...&lt;/p&gt;&lt;p&gt;La segunda contiene 4 parámetros necesarios, más 4 opcionales y su sintaxis es la siguiente:&lt;/p&gt;&lt;blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"&gt;&lt;p style="text-align: left;"&gt;&lt;b&gt;OW3.$totpvalidate&lt;/b&gt;(&lt;i&gt;xSharedSecretKey&lt;/i&gt;,&lt;i&gt;iTimeStep&lt;/i&gt;,&lt;i&gt;iDigits&lt;/i&gt;,&lt;i&gt;iTOTP&lt;/i&gt;[,&lt;i&gt;&amp;amp;cErrorText&lt;/i&gt;,&lt;i&gt;iHashType&lt;/i&gt;=kOW3hashSHA1,&lt;i&gt;iStepsBefore&lt;/i&gt;=2,&lt;i&gt;iStepsAfter&lt;/i&gt;=1])&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Esta función valida la contraseña de un solo uso con base en el tiempo, contenida en&amp;nbsp;&lt;i&gt;iTOTP&lt;/i&gt;&amp;nbsp;utilizando para ello el algoritmo TOTP. Retornado "true" si&amp;nbsp;&lt;i&gt;iTOTP&lt;/i&gt; resulta en un TOTP válido.&lt;/p&gt;&lt;p&gt;Parámetros obligatorios:&lt;/p&gt;&lt;p&gt;&lt;i&gt;xSharedSecretKey&lt;/i&gt;&amp;nbsp;(Binary) es la clave secreta compartida, su longitud debe estar entre 16 y 256 bytes.&lt;/p&gt;&lt;p&gt;&lt;i&gt;TimeStep&lt;/i&gt;&amp;nbsp;(Integer 32 bit) es el salto de tiempo en segundos el cual deberá estar entre 1 y 3600.&lt;/p&gt;&lt;p&gt;&lt;i&gt;iDigits&lt;/i&gt;&amp;nbsp;(Integer 32 bit) es el número de dígitos del TOTP resultante,&amp;nbsp;un valor entre 6 y 8.&lt;/p&gt;&lt;p&gt;&lt;i&gt;iTOTP&lt;/i&gt;&amp;nbsp;(Integer 32 bit) es el TOTP que va a ser validado.&lt;/p&gt;&lt;p&gt;Parámetros opcionales:&lt;/p&gt;&lt;p&gt;&lt;i&gt;cErrorText&lt;/i&gt;&amp;nbsp;(Character 100000000) Si se proporciona, recibirá la descripción del posible error provocado por $totpgenerate o $totpvalidate (si resultó "false").&lt;/p&gt;&lt;p&gt;&lt;i&gt;iHashType&lt;/i&gt;&amp;nbsp;(Integer 32 bit), su valor por defecto es proporcionado por la constante kOW3hashSHA1) es el tipo de "hash" a utilizar, use una de las constantes del grupo kOW3hash...&lt;/p&gt;&lt;p&gt;&lt;i&gt;iStepsBefore&lt;/i&gt; (Integer 32 bit), el valor por defecto es 2 y es el número de saltos de tiempo anteriores al momento actual, para llevar a cabo la verificación del TOTP proporcionado, deberá ser un valor entre 1 y 20.&lt;/p&gt;&lt;p&gt;&lt;i&gt;iStepsAfter&lt;/i&gt; (Integer 32 bit), su valor por defecto es 1 y es el número de saltos de tiempo después del momento actual, para llevar a cabo&amp;nbsp;la verificación del TOTP proporcionado, deberá ser un valor entre 1 y 20.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Omnis en GitHub</title><link>http://framosmu.blogspot.com/2020/11/blog-post.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Thu, 26 Nov 2020 12:12:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-1126117781890730838</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://www.omnis.net/blog/add-power-and-functionality-to-omnis-studio-your-libraries-with-open-source-components/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="818" data-original-width="1316" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxh6M38cKlq_mdrikwXd06CXd8ZgnWAmkruAFRK2i9RyT_ACyJZ9LfSuUvzWJEERO9_iutUmTywhOpzkscFCw38maPZiyBdSclMLVZjymvzTtO5QnYqLgxB4noVjiohVYvgl-G/w640-h398/Omnis_on_Github6.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxh6M38cKlq_mdrikwXd06CXd8ZgnWAmkruAFRK2i9RyT_ACyJZ9LfSuUvzWJEERO9_iutUmTywhOpzkscFCw38maPZiyBdSclMLVZjymvzTtO5QnYqLgxB4noVjiohVYvgl-G/s72-w640-h398-c/Omnis_on_Github6.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Nuevo asistente para la construcción de aplicaciones finales (Deployment Tool)</title><link>http://framosmu.blogspot.com/2020/07/nuevo-asistente-para-la-construccion-de.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Fri, 3 Jul 2020 12:06:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-8086336878467349117</guid><description>&lt;div style="text-align: justify;"&gt;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.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style="text-align: justify;"&gt;Opciones macOS&lt;/h2&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;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:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRHgvjcVh4NQuzCf5W2u7MUdXaIdZrem1MBWU1iPm6z5L0SOa6t4tXAuwgtgOcrtZa0Z9R90VcNmKFTBgSS3ab9TUXmxd3Ep3JhqMismZca-k-X1K8vU-9ACcrJPw9RgW_Ay20/s808/Imagen+1.png" imageanchor="1"&gt;&lt;img border="0" data-original-height="176" data-original-width="808" height="138" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRHgvjcVh4NQuzCf5W2u7MUdXaIdZrem1MBWU1iPm6z5L0SOa6t4tXAuwgtgOcrtZa0Z9R90VcNmKFTBgSS3ab9TUXmxd3Ep3JhqMismZca-k-X1K8vU-9ACcrJPw9RgW_Ay20/w625-h138/Imagen+1.png" width="625" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;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.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg55LIoSF74XKiPyBMLsVfS1M-mbwa1kw63-wD8OFogfrAKt02OvPlD6MYnjNWMdinz2FD34TiZV1fG6vWeAEz0qXkdKdD5OcGngedjRw4QXzP5lQwUg4_luqwY-ehq8Xofy2TD/s814/Imagen+2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="172" data-original-width="814" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg55LIoSF74XKiPyBMLsVfS1M-mbwa1kw63-wD8OFogfrAKt02OvPlD6MYnjNWMdinz2FD34TiZV1fG6vWeAEz0qXkdKdD5OcGngedjRw4QXzP5lQwUg4_luqwY-ehq8Xofy2TD/w625-h133/Imagen+2.png" width="625" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;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.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style="clear: both; text-align: left;"&gt;Opciones Windows&lt;/h2&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;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.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD-4c6lbQwqNDphv9QbiV0UL-ygs2WoC05lfYMl8FRfo3O5Fp6QtZUxCrkn2L8v6OuDatrB1lharRplzgA9DI5_NHMeCqYTbBeWks-MqiQYcQJx6EJ5MTFxo1ged-0OSF06r7B/s824/Imagen+3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="152" data-original-width="824" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD-4c6lbQwqNDphv9QbiV0UL-ygs2WoC05lfYMl8FRfo3O5Fp6QtZUxCrkn2L8v6OuDatrB1lharRplzgA9DI5_NHMeCqYTbBeWks-MqiQYcQJx6EJ5MTFxo1ged-0OSF06r7B/w625-h116/Imagen+3.png" width="625" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;Desde la segunda pantalla (como en el caso de macOS) podremos especificar su "startup", "&lt;span style="text-align: justify;"&gt;iconsets&lt;/span&gt;", "xcomp" e &lt;span style="text-align: justify;"&gt;"icons"&lt;/span&gt;, así como la opción para pre-serializar el paquete o agregar un directorio de lectura/escritura personalizado.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9OCqvIM-4VvwpZnnvmlgmSULaO7y0rlqgn7gPSLOhsnfrT57PIm7oP09rKr-UJTfq_XYbvPrY_q4ozjT1wuBRgwXDSRiy4JXAxCDneef0UWTDFgdodq8LwR_5OXshLBV-xqWU/s832/Imagen+4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="154" data-original-width="832" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9OCqvIM-4VvwpZnnvmlgmSULaO7y0rlqgn7gPSLOhsnfrT57PIm7oP09rKr-UJTfq_XYbvPrY_q4ozjT1wuBRgwXDSRiy4JXAxCDneef0UWTDFgdodq8LwR_5OXshLBV-xqWU/w625-h116/Imagen+4.png" width="625" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;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",&amp;nbsp;si se produce algún error durante el proceso.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjby3K2oDS5Sy-LTTYGgAJIXfiuVCMqtyyQc6HDxywNghW4hqExiK-SeUhCKLWRkU-MkbYp0erLd_jfuwRoT5OO-2fx8pAEk2taSH_mXGopFUPWwz_ybE0baQuscdl_-DPApNqn/s824/Imagen+5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="152" data-original-width="824" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjby3K2oDS5Sy-LTTYGgAJIXfiuVCMqtyyQc6HDxywNghW4hqExiK-SeUhCKLWRkU-MkbYp0erLd_jfuwRoT5OO-2fx8pAEk2taSH_mXGopFUPWwz_ybE0baQuscdl_-DPApNqn/w625-h116/Imagen+5.png" width="625" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;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&amp;nbsp;con inclusión del instalador inicial "Split tree with firstruninstall".&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;ul&gt;&lt;li&gt;La opción "Flat tree" generará una carpeta simple con todos los archivos, los de lectura y los de lectura/escritura.&lt;/li&gt;&lt;li&gt;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".&lt;/li&gt;&lt;li&gt;La opción "Split Tree with firstruninstall" generará una carpeta con los archivos de solo lectura y dentro de esta,&amp;nbsp; 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.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;Uso del editor de recursos "RCEdit"&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;$setapplicationmanifest(cFile, cManifest)&lt;/b&gt;, 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&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;$setresourcestring(cFile, cResource, cValue)&lt;/b&gt;, 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&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;$setproductversion(cFile, cProductVersion)&lt;/b&gt;,&amp;nbsp;cambia el recurso del ejecutable Windows "Product Version" según lo indicado en cProductVersion para la ruta del archivo cFile, ejemplo:&amp;nbsp;Do rcedit.$setproductversion(“C:\omnis.exe”, “10.1”)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;$seticon(cFile, cIcon)&lt;/b&gt;,&amp;nbsp;cambia el icono del ejecutable Windows indicado la ruta del archivo cFile, por el archivo ".ico", indicado en la ruta cIcon, ejemplo:&amp;nbsp;Do rcedit.$seticon(“C:\omnis.exe”, “C:\newIcon.ico”) Returns #F&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;$setversionstring(cFile, cVersion, cValue)&lt;/b&gt;,&amp;nbsp;cambia el texto de versión en "cVersion" por el especificado en "cValue" según la ruta indicada en cFile, ejemplo:&amp;nbsp;Do rcedit.$setversionstring(“C:\omnis.exe”, “Comments”, “Comment version string”) Returns #F&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;$setfileversion(cFile, cFileVersion)&lt;/b&gt;,&amp;nbsp;cambia el recurso del ejecutable Windows "File Version" por el contenido en cFileVersion, ejemplo:&amp;nbsp;Do rcedit.$setfileversion(“C:\omnis.exe”, “10.1.0.0”) Returns #F&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRHgvjcVh4NQuzCf5W2u7MUdXaIdZrem1MBWU1iPm6z5L0SOa6t4tXAuwgtgOcrtZa0Z9R90VcNmKFTBgSS3ab9TUXmxd3Ep3JhqMismZca-k-X1K8vU-9ACcrJPw9RgW_Ay20/s72-w625-h138-c/Imagen+1.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><georss:featurename xmlns:georss="http://www.georss.org/georss">Salamanca, España</georss:featurename><georss:point xmlns:georss="http://www.georss.org/georss">40.9701039 -5.6635396999999994</georss:point><georss:box xmlns:georss="http://www.georss.org/georss">12.659870063821153 -40.8197897 69.280337736178836 29.4927103</georss:box></item><item><title>Cómo mostrar un PDF desde un campo BLOB de Oracle sobre el navegador, sin descargarlo</title><link>http://framosmu.blogspot.com/2020/02/como-mostrar-un-pdf-desde-un-campo-blob.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Thu, 13 Feb 2020 12:55:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-3651106277498384497</guid><description>&lt;div style="text-align: justify;"&gt;
En este artículo quiero mostrarles un "truco" ideado por&amp;nbsp;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.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiRvONkNI1jqcVDdL2J0zBuqvvGZLoy8bUVLtpvNZIQWkChcyop_UApEGZme41rS9auiDw7Y5jUx4qsKzs5Rg25tmzeNwqYuGo2VvQG1bPBXVGmygB_FlQ2LecefLUZc14GH8S/s1600/images.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="168" data-original-width="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiRvONkNI1jqcVDdL2J0zBuqvvGZLoy8bUVLtpvNZIQWkChcyop_UApEGZme41rS9auiDw7Y5jUx4qsKzs5Rg25tmzeNwqYuGo2VvQG1bPBXVGmygB_FlQ2LecefLUZc14GH8S/s1600/images.jpeg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En principio podría pensarse que se trata de algo sencillo de hacer desde Omnis Studio, ya conocemos el método&amp;nbsp;&lt;i&gt;Do $cinst.$clientcommand("assignpdf",row)&lt;/i&gt; donde el parámetro row se define como &lt;i&gt;row(html-object-name,pdf-parameters,pdf-id,timeout,pdf-filename)&lt;/i&gt;, pero el reto está precisamente en el parámetro &lt;i&gt;pdf-filename&lt;/i&gt;, 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.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La parte digamos "sencilla" fue construir el método (denominado &lt;b&gt;muestraPdf&lt;/b&gt;) javascript que se encargaría de mostrar el documento, pasándole el contenido del campo BLOB de oracle y que mostramos a continuación:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;div style="font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt;"&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: red;"&gt;#&lt;/span&gt;&lt;span style="color: red;"&gt;&amp;nbsp;El dato BLOB de Oracle es iDocumentos.DOCUMENTO&lt;/span&gt;&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: red;"&gt;#&lt;/span&gt;&lt;span style="color: red;"&gt;&amp;nbsp;pdfBuffer es una variable var de JavaScript&lt;/span&gt;&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: red;"&gt;#&lt;/span&gt;&lt;span style="color: red;"&gt;&amp;nbsp;el método ha sido marcado como "Execute On Client"&lt;/span&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;div style="font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt;"&gt;
&lt;br /&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;Calculate&lt;/span&gt;&amp;nbsp;&lt;span style="color: #6666ff; font-weight: bold;"&gt;pdfBuffer&lt;/span&gt;&lt;span style="color: #996600;"&gt;&amp;nbsp;as&amp;nbsp;&lt;/span&gt;&lt;span style="color: #ff6666; font-weight: bold;"&gt;iDocumentos&lt;/span&gt;.&lt;span style="color: green;"&gt;DOCUMENTO&lt;/span&gt;&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;var arrayBuffer = base64ToArrayBuffer(pdfBuffer);&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;function base64ToArrayBuffer(base64) {&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;var binaryString = window.atob(base64);&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;var binaryLen = binaryString.length;&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;var bytes = new Uint8Array(binaryLen);&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;for (var i = 0; i &amp;lt; binaryLen; i++) {&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;var ascii = binaryString.charCodeAt(i);&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;bytes[i] = ascii;&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;}&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;return bytes;&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;}&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;var blob = new Blob([arrayBuffer], {type:&amp;nbsp;&lt;span style="color: maroon;"&gt;"application/pdf"&lt;/span&gt;});&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;var link = window.URL.createObjectURL(blob);&lt;/div&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;JavaScript:&lt;/span&gt;&amp;nbsp;window.open(link);&lt;/div&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
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".&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Para que la magia tenga su efecto, lo primero que hacemos es colocar un "Timer Control" sobre el formulario remoto...&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2X1-HX29h7zpcJG6mGGrkETZHH3X4dvdRZrH4PjdnQ4zM2k0g1bATvyJZDV7VAbvknQrl-3Auf-L1hmi_BYswZiSQQ6oqed4gc_9nTMe6MnJBGvAXiuVSF6VnzobkFrcEFX_u/s1600/Captura+de+pantalla+2020-02-13+a+las+12.28.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="340" data-original-width="400" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2X1-HX29h7zpcJG6mGGrkETZHH3X4dvdRZrH4PjdnQ4zM2k0g1bATvyJZDV7VAbvknQrl-3Auf-L1hmi_BYswZiSQQ6oqed4gc_9nTMe6MnJBGvAXiuVSF6VnzobkFrcEFX_u/s320/Captura+de+pantalla+2020-02-13+a+las+12.28.02.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
...al que incluiremos en su método "&lt;i&gt;$event&lt;/i&gt;" el código siguiente y que estratégicamente habremos marcado como "Execute On Client":&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;div style="font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt;"&gt;
&lt;div style="padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;On&lt;/span&gt;&amp;nbsp;evTimer&lt;/div&gt;
&lt;div style="margin-left: 1em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;Do&lt;/span&gt;&amp;nbsp;&lt;span style="color: #bb00bb;"&gt;$cinst.$objs&lt;/span&gt;.&lt;span style="color: green;"&gt;timerObj&lt;/span&gt;.&lt;span style="color: #bb00bb;"&gt;$running.$assign&lt;/span&gt;(&lt;span style="color: #00cc33;"&gt;kFalse&lt;/span&gt;)&lt;/div&gt;
&lt;div style="margin-left: 1em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;Do&lt;/span&gt;&amp;nbsp;&lt;span style="color: #bb00bb;"&gt;$cinst.&lt;/span&gt;&lt;span style="color: green;"&gt;$muestraPdf&lt;/span&gt;()&lt;/div&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
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.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
A continuación mostramos la secuencia que obtiene el campo BLOB de oracle y activa el timer:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;div style="font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt;"&gt;
&lt;div style="margin-left: 3em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;Calculate&lt;/span&gt;&amp;nbsp;&lt;span style="color: #6666ff; font-weight: bold;"&gt;lCompara&lt;/span&gt;&lt;span style="color: #996600;"&gt;&amp;nbsp;as&amp;nbsp;&lt;/span&gt;&lt;span style="color: #00a0a0;"&gt;con&lt;/span&gt;(&lt;span style="color: maroon;"&gt;"where ROWID = '"&lt;/span&gt;;&lt;span style="color: #ff6666; font-weight: bold;"&gt;iListaDctos&lt;/span&gt;.&lt;span style="color: green;"&gt;ROWID&lt;/span&gt;;&lt;span style="color: maroon;"&gt;"'"&lt;/span&gt;)&lt;/div&gt;
&lt;div style="margin-left: 3em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;Do&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff6666; font-weight: bold;"&gt;iDocumentos&lt;/span&gt;.&lt;span style="color: #bb00bb;"&gt;$select&lt;/span&gt;(&lt;span style="color: #6666ff; font-weight: bold;"&gt;lCompara&lt;/span&gt;)&amp;nbsp;&lt;span style="color: #996600;"&gt;Returns&amp;nbsp;&lt;/span&gt;&lt;span style="color: grey;"&gt;#F&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin-left: 3em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;If flag true&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin-left: 4em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;Do&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff6666; font-weight: bold;"&gt;iDocumentos&lt;/span&gt;.&lt;span style="color: #bb00bb;"&gt;$fetch&lt;/span&gt;()&lt;/div&gt;
&lt;div style="margin-left: 4em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;If&lt;/span&gt;&amp;nbsp;&lt;span style="color: #00a0a0;"&gt;not&lt;/span&gt;(&lt;span style="color: #00a0a0;"&gt;isclear&lt;/span&gt;(&lt;span style="color: #ff6666; font-weight: bold;"&gt;iDocumentos&lt;/span&gt;.&lt;span style="color: green;"&gt;DOCUMENTO&lt;/span&gt;))&lt;/div&gt;
&lt;div style="margin-left: 5em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;Do&lt;/span&gt;&amp;nbsp;&lt;span style="color: #bb00bb;"&gt;$cinst.$objs&lt;/span&gt;.&lt;span style="color: green;"&gt;timerObj&lt;/span&gt;.&lt;span style="color: #bb00bb;"&gt;$running.$assign&lt;/span&gt;(&lt;span style="color: #00cc33;"&gt;kTrue&lt;/span&gt;)&lt;/div&gt;
&lt;div style="margin-left: 4em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;End If&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin-left: 3em; padding: 0px;"&gt;
&lt;span style="color: #996600;"&gt;End If&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Gracias de nuevo a&amp;nbsp;&lt;span style="text-align: justify;"&gt;Francesco de soporte Omnis, por este maravilloso truco.&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiRvONkNI1jqcVDdL2J0zBuqvvGZLoy8bUVLtpvNZIQWkChcyop_UApEGZme41rS9auiDw7Y5jUx4qsKzs5Rg25tmzeNwqYuGo2VvQG1bPBXVGmygB_FlQ2LecefLUZc14GH8S/s72-c/images.jpeg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>La librería de conversión de DML a SQLite</title><link>http://framosmu.blogspot.com/2020/01/la-libreria-de-conversion-de-dml-sqlite.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><category>OMSQLDAM</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Wed, 22 Jan 2020 13:57:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-338364397693061476</guid><description>&lt;div style="text-align: justify;"&gt;
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.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0e8Ebqmeur_OZFbpUE-aqVHh93cKLpXf-ret6q5LvnaCQA2cfMvCTJHHN2IH46y3r_NjQzl4jNb1Tr8ydbS6dHZ7tJN_oBtaOf2eGAhEYOApsve4cUvgnfmHGlqy_eVtGnaY1/s1600/images.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="142" data-original-width="355" height="128" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0e8Ebqmeur_OZFbpUE-aqVHh93cKLpXf-ret6q5LvnaCQA2cfMvCTJHHN2IH46y3r_NjQzl4jNb1Tr8ydbS6dHZ7tJN_oBtaOf2eGAhEYOApsve4cUvgnfmHGlqy_eVtGnaY1/s320/images.jpeg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
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:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq" style="text-align: justify;"&gt;
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(),&amp;nbsp;Build indexes, Delete data, Drop indexes, Open runtime datafile browser, Rename data,&amp;nbsp;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,&amp;nbsp;Clear all files, Clear main &amp;amp; connected, Clear main file, Clear range of fields, Clear selected files, Set main file,&amp;nbsp;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,&amp;nbsp;Clear search class, Reinitialize search class, Set search as calculation, Set search name, Test data with search class,&amp;nbsp;Clear sort fields, Set sort field,&amp;nbsp;Build list from file,&amp;nbsp;Begin reversible block, End reversible block, Quit all methods, $root.$getodbfilelist(), y alguna funciones de sys(), como:&amp;nbsp;sys(11), sys(139), sys(3000) &amp;amp; sys(3001)&lt;/blockquote&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Para habilitar la emulación de comandos DML, es necesario establecer la preferencia de&amp;nbsp;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:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;b&gt;Open datafile sdb://192.168.0.10:5743/SQLiteTest&lt;/b&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Pero si queremos también podemos optar por cambiar éste comando y hacer uso de la sintaxis de notación del modo siguiente:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;b&gt;Do omsqlSess.$logon(‘sdb://192.168.0.10:5743/SQLiteTest’,’’,’’) Returns #F&lt;/b&gt;&lt;/blockquote&gt;
&lt;br /&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0e8Ebqmeur_OZFbpUE-aqVHh93cKLpXf-ret6q5LvnaCQA2cfMvCTJHHN2IH46y3r_NjQzl4jNb1Tr8ydbS6dHZ7tJN_oBtaOf2eGAhEYOApsve4cUvgnfmHGlqy_eVtGnaY1/s72-c/images.jpeg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>¿Cómo evitar el diálogo "Install the legacy Java SE 6 runtime" en Omnis Studio 10.1 y Catalina?</title><link>http://framosmu.blogspot.com/2019/10/como-evitar-el-dialogo-install-legacy.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><category>#SOA</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Tue, 15 Oct 2019 10:47:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-821260515629774466</guid><description>&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Es muy probable que tras instalar de nuevo el soporte Java para SOAP en Omnis Studio 10.1, nos encontremos con&amp;nbsp;que Omnis nos muestre un cuadro de diálogo Java que tenga el siguiente texto;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhunhKMcOMT4Fpal76OYJsVCoOTRhyphenhyphenjz2NEyv2FStHza-Qm0_o71QJhd8AbNBXiHg8RB1_PnNm3Tk8OT6vFTHn3v_ozUsksRXD345U6bToijJoa9leKCW_k4c1gvzfdVKgFrvms/s1600/Aviso.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="534" data-original-width="1064" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhunhKMcOMT4Fpal76OYJsVCoOTRhyphenhyphenjz2NEyv2FStHza-Qm0_o71QJhd8AbNBXiHg8RB1_PnNm3Tk8OT6vFTHn3v_ozUsksRXD345U6bToijJoa9leKCW_k4c1gvzfdVKgFrvms/s400/Aviso.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Este cuadro de diálogo puede aparecer aún al intentar iniciar una JVM de Oracle en una versión de Studio de 64 bits, es decir, Studio 8.0 y posterior. Las instrucciones predeterminadas establecidas en una versión de Java de 64 bits &lt;b&gt;no permiten&lt;/b&gt; que sean iniciadas desde una aplicación incluida en JNI (como es el caso de Omnis). Lo cual causará un fallo el intentar iniciar la JVM mostrándose el mensaje anterior.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Para corregirlo, simplemente debemos editar el fichero "Info.plist" de nuestro Oracle JDK en uso, para permitir que JVM sea iniciado desde aplicaciones incluidas en JNI.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
Podrá localizar el fichero a editar en, "/Library/Java/JavaVirtualMachines/jdkX.X.X_XXX.jdk/Contents/Info.plist" (donde X.X.X_XXX es la versión, por ejemplo, 1.8.0_101).&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
Ahora simplemente cambie la entrada:&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span class="codetext" style="color: #222222; font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , &amp;quot;lucida sans typewriter&amp;quot; , &amp;quot;lucida typewriter&amp;quot; , monospace; font-size: 18px; overflow-wrap: break-word;"&gt;≤key≥JVMCapabilities≤/key≥&lt;br /&gt;≤array≥&lt;br /&gt;&amp;nbsp;&amp;nbsp; ≤string≥CommandLine≤/string≥&lt;br /&gt;≤/array≥&lt;/span&gt;&lt;/blockquote&gt;
por:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="background-color: white; color: #222222; font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , &amp;quot;lucida sans typewriter&amp;quot; , &amp;quot;lucida typewriter&amp;quot; , monospace; font-size: 18px;"&gt;&amp;nbsp; &amp;nbsp;≤key≥JVMCapabilities≤/key≥&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white; color: #222222; font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , &amp;quot;lucida sans typewriter&amp;quot; , &amp;quot;lucida typewriter&amp;quot; , monospace; font-size: 18px;"&gt;&amp;nbsp; &amp;nbsp;≤array≥&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white; color: #222222; font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , &amp;quot;lucida sans typewriter&amp;quot; , &amp;quot;lucida typewriter&amp;quot; , monospace; font-size: 18px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ≤string≥CommandLine≤/string≥&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white; color: #222222; font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , &amp;quot;lucida sans typewriter&amp;quot; , &amp;quot;lucida typewriter&amp;quot; , monospace; font-size: 18px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ≤string≥JNI≤/string≥&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white; color: #222222; font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , &amp;quot;lucida sans typewriter&amp;quot; , &amp;quot;lucida typewriter&amp;quot; , monospace; font-size: 18px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ≤string≥BundledApp≤/string≥&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #222222; font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , &amp;quot;lucida sans typewriter&amp;quot; , &amp;quot;lucida typewriter&amp;quot; , monospace; font-size: 18px;"&gt;&amp;nbsp; &amp;nbsp;≤/array&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
..y eso habrá sido todo.&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhunhKMcOMT4Fpal76OYJsVCoOTRhyphenhyphenjz2NEyv2FStHza-Qm0_o71QJhd8AbNBXiHg8RB1_PnNm3Tk8OT6vFTHn3v_ozUsksRXD345U6bToijJoa9leKCW_k4c1gvzfdVKgFrvms/s72-c/Aviso.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>¿Cómo Ignorar el aviso de actualización a Catalina?</title><link>http://framosmu.blogspot.com/2019/10/como-ignorar-el-aviso-de-actualizacion.html</link><category>#AULAOMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Fri, 11 Oct 2019 12:30:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-3023178878389663461</guid><description>Tengo un iMac en casa y otro en el trabajo, pero en el del trabajo no puedo actualizar a Catalina, ya que necesito seguir dando soporte a aplicaciones más antiguas, pero quiero eliminar el mensaje que me solicita actualizar a Catalina, de modo que quiero "saltar" (de momento) su actualización, ¿Podemos hacerlo?&lt;br /&gt;
&lt;br /&gt;
Afortunadamente sí, sólo necesitas introducir el siguiente comando...&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="background-color: #d7dce5; color: #e83e8c; font-family: , &amp;quot;menlo&amp;quot; , &amp;quot;monaco&amp;quot; , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;courier new&amp;quot; , monospace; font-size: 15.75px;"&gt;sudo softwareupdate --ignore "macOS Catalina"&lt;/span&gt;&lt;/blockquote&gt;
&amp;nbsp;..si más adelante deseas volver a la situación anterior, introduce...&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="background-color: #d7dce5; color: #e83e8c; font-family: , &amp;quot;menlo&amp;quot; , &amp;quot;monaco&amp;quot; , &amp;quot;consolas&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;courier new&amp;quot; , monospace; font-size: 15.75px;"&gt;sudo softwareupdate --reset-ignored&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
...y ¡ya está! no correrás el peligro de que puedas actualizar a Catalina en un momento no deseado.</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Conexión nativa a Microsoft SQL Server con Omnis Studio 10</title><link>http://framosmu.blogspot.com/2019/09/conexion-nativa-microsoft-sql-server.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Mon, 16 Sep 2019 14:07:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-3317306065761868298</guid><description>&lt;div style="text-align: justify;"&gt;
Recientemente el DAM para Sybase de Omnis Studio 10, ha sido modificado para su uso mediante la versión "open-source" de LIBCT desarrollada por FreeTDS. FreeTDS facilita principalmente conexión libre de uso, para servidores Sybase ASE y Sybase ASA. Pero resulta que la librería LIBCT de FreeTDS, también soporta conexiones nativas a Microsoft SQLServer, anteriormente, esto sólo era posible mediante los DAM ODBC o JDBC.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl4eIqQAUfPHLieFMFuX3v0E4FUulzb0orwKNNiTkCA-NmXu8S583lt0v-u8BTLjycsrFv7LlgWeBq1g4rq6ULViGOXxR2AmF7lzimFoXAaIwzN4fXQ7VO5VfqqNQfpDrgnjw5/s1600/tnsq0036_pic1.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl4eIqQAUfPHLieFMFuX3v0E4FUulzb0orwKNNiTkCA-NmXu8S583lt0v-u8BTLjycsrFv7LlgWeBq1g4rq6ULViGOXxR2AmF7lzimFoXAaIwzN4fXQ7VO5VfqqNQfpDrgnjw5/s1600/tnsq0036_pic1.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="299" data-original-width="382" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl4eIqQAUfPHLieFMFuX3v0E4FUulzb0orwKNNiTkCA-NmXu8S583lt0v-u8BTLjycsrFv7LlgWeBq1g4rq6ULViGOXxR2AmF7lzimFoXAaIwzN4fXQ7VO5VfqqNQfpDrgnjw5/s320/tnsq0036_pic1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6xxi6cmCr4XmoecHKo685dE9kIXZ0NJjgANlUt3_QnZ7HEy3mXj04zUagNdKjYgT7EWkBAO1wfvoVJonqZodVDignQMJm2GdtJ29wDexwLcLA5kS-ADVofJKRceT-xb9XXyYV/s1600/tnsq0036_pic2.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="423" data-original-width="657" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6xxi6cmCr4XmoecHKo685dE9kIXZ0NJjgANlUt3_QnZ7HEy3mXj04zUagNdKjYgT7EWkBAO1wfvoVJonqZodVDignQMJm2GdtJ29wDexwLcLA5kS-ADVofJKRceT-xb9XXyYV/s320/tnsq0036_pic2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
La nota técnica: &lt;a href="https://omnis.net/developers/resources/technotes/tnsq0036.jsp"&gt;https://omnis.net/developers/resources/technotes/tnsq0036.jsp&lt;/a&gt; le dará más detalles sobre como configurar el DAM para su uso con Microsoft SQLServer.&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl4eIqQAUfPHLieFMFuX3v0E4FUulzb0orwKNNiTkCA-NmXu8S583lt0v-u8BTLjycsrFv7LlgWeBq1g4rq6ULViGOXxR2AmF7lzimFoXAaIwzN4fXQ7VO5VfqqNQfpDrgnjw5/s72-c/tnsq0036_pic1.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Acceso a datos con aplicaciones Web</title><link>http://framosmu.blogspot.com/2019/08/acceso-datos-con-aplicaciones-web.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Fri, 30 Aug 2019 12:39:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-8584625020907493553</guid><description>&lt;div style="text-align: justify;"&gt;
Una buena práctica cuando estamos creando aplicaciones para la Web con Omnis Studio, consiste en la creación de un grupo de sesiones (session pool) para controlar el acceso a datos por parte de los usuarios de la aplicación Web. La idea es otorgar a cada usuario activo de la aplicación una sesión individual de acceso a datos, mejorando así los tiempos de acceso, ya que la base de datos podrá atender simultáneamente las peticiones de cada uno de los clientes.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKB4Nror0UYO_wl-uyRu2dF620XMAA3twqsg-Z6hqDTv-hTOZ7OQKtanRoRVBRninMjuwlZ_eKPeyqpGaxQlu8_ZeWlInFtGydyhVGeEhsl8s8zUT2B-DLP6BDecuEV_4UBLUo/s1600/Cliente-Servidor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="222" data-original-width="461" height="154" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKB4Nror0UYO_wl-uyRu2dF620XMAA3twqsg-Z6hqDTv-hTOZ7OQKtanRoRVBRninMjuwlZ_eKPeyqpGaxQlu8_ZeWlInFtGydyhVGeEhsl8s8zUT2B-DLP6BDecuEV_4UBLUo/s320/Cliente-Servidor.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;span id="goog_130865290"&gt;&lt;/span&gt;&lt;span id="goog_130865291"&gt;&lt;/span&gt;&lt;br /&gt;
El método Omnis que nos permite hacer esto se denomina $makepool, puesto que Omnis creará el grupo de sesiones de modo global (bajo $root), parece lógico invocarlo desde un método (por ejemplo $acceso) situado en la clase "Startup_Task" y que será ejecutado desde su $construct. Eso garantizará que cada vez que se haga disponible nuestra aplicación Web (se abra la librería) el grupo sea automáticamente creado. El código será algo como esto:&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq" style="text-align: left;"&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;b&gt;Do $extobjects.PGSQLDAM.$objects.PGSQLSESS.$makepool('myPool',1,'192.168.10.10','myUser','myPassword') Returns iMyPoolRef&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
El segundo parámetro (1 en el ejemplo) es el número de sesiones de que constará el grupo inicialmente, lo cual no plantea ningún problema, ya que todo "session pool", dispone de propiedades que nos permiten (entre otras cosas) aumentar ésta cifra según surja la necesidad debido al incremento en el número de usuarios que esten haciendo uso de la aplicación Web, o simplemente conocer su cifra actual.&lt;br /&gt;
&lt;br /&gt;
El primer parámetro del método $makepool es el nombre que identifica al grupo de sesiones de modo único. Dado que su existencia es global (nivel $root), deberá eliminarse cuando se destruya su "Startup_Task"". Esto significa que no podrá existir otro grupo de sesiones con el mismo nombre. La variable "iMyPoolRef" nos permite referenciar al grupo creado, pero tambien disponemos de un modo para conocer todos los posibles y diferentes grupos de sesiones que puedan llegar a existir bajo un mismo servidor de aplicaciones Omnis, en $sessionpools.&lt;br /&gt;
&lt;br /&gt;
Para cerrar el grupo de sesiones, usaremos el siguiente código situado en el método $destruct de nuestra clase "Startup_Task":&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;b&gt;Do $sessionpools.$remove(iMyPoolRef)&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Note que "iMyPoolRef" es una variable de instancia y tipo "Item Reference" cuyo valor ha sido asignado por el método $makepool.&lt;br /&gt;
&lt;br /&gt;
Ahora explicaremos cómo solicitar una nueva sesión al grupo, con el fin de otorgársela al usuario durante el tiempo que esté usando nuestra aplicación Web, para ello usaremos el metodo $new. Con éste fin crearemos un nuevo método en nuestra clase "Startup_Task" al que denominaremos $getSessionFromPool, con el siguiente código:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq" style="text-align: left;"&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;b&gt;If iSessionPoolRef.$poolsize=iSessionPoolRef.$inuse&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class="tr_bq" style="text-align: left;"&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;b&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Do iSessionPoolRef.$poolsize.$assign(iSessionPoolRef.$inuse+1)&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class="tr_bq" style="text-align: left;"&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;b&gt;End If&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class="tr_bq" style="text-align: left;"&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;b&gt;Quit method iSessionPoolRef.$new()&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
El tamaño del grupo de sesiones ($poolsize) puede ser aumentado en cualquier momento, nosotros lo haremos comprobando si se ha alcanzado su límite actual ($poolsize=$inuse) y cada vez que requiramos de una nueva sesión. El método $new retornará un nuevo objeto de sesión para acceso a datos.&lt;br /&gt;
&lt;br /&gt;
Ahora nos queda una cuestión importante por resolver, ¿Cómo ejecutar el método $getSessionFromPool ubicado en la calse "Startup_Task" desde una clase "Remote_task"?&lt;br /&gt;
&lt;br /&gt;
Naturalmente necesitamos hacerlo así, ya que queremos asignar la nueva sesión a cada nueva conexión remota. Empezaremos por crear una variable de tipo task, en la clase "Remote_task", donde alojar el nuevo objeto de acceso a datos, la llamaremos "tSessionObj", también resultará lógico que el código para invocar al método $getSessionFromPool lo situemos en el método $construct de la "Remote_task", la respuesta a la pregunta del párrafo anterior sería:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;b&gt;Do $itasks.myLib.$getSessionFromPool() Returns tSessionObj&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
El literal "myLib" deberá corresponder al nombre de nuestra librería o bien usar la notación [$clib().$name] (importante usar los corchetes) para obtener el nombre de la misma, si optamos por esto último estaríamos garantizando su funcionamiento aunque se llegue a cambiar el nombre asignado inicialmente a la librería.&lt;br /&gt;
&lt;br /&gt;
Esto es todo o casi todo, ahora sólo nos quedaría asignar la sesión (normalmente) a la o las clases "table" que use nuestra aplicación Web, para esto lo más habitual es disponer de una super-clase "table" que será heredada por el resto de clases "table", de ese modo escribiremos nuestro código de asignación de sesión una única vez.&lt;br /&gt;
&lt;br /&gt;
Suponiendo que el nombre de nuestra super-clase es "taSuper", escribiríamos en su método $construct lo siguiente:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq" style="text-align: left;"&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;b&gt;Do $cinst.$sessionobject.$assign(tSessionObj)&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Naturalmente el resto de clases "table", heredaran este método constructor, aunque también pueden tener el suyo propio, pero si lo usamos, tendremos que utilizar el comando "Do inherited" para ordenar la ejecución del método $construct en la superclase.&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKB4Nror0UYO_wl-uyRu2dF620XMAA3twqsg-Z6hqDTv-hTOZ7OQKtanRoRVBRninMjuwlZ_eKPeyqpGaxQlu8_ZeWlInFtGydyhVGeEhsl8s8zUT2B-DLP6BDecuEV_4UBLUo/s72-c/Cliente-Servidor.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Creación de paquetes firmados para la instalación de aplicaciones Omnis en MacOS</title><link>http://framosmu.blogspot.com/2019/05/creacion-de-paquetes-firmados-para-la.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Fri, 24 May 2019 12:18:00 +0200</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-1237685839712635139</guid><description>&lt;div style="text-align: justify;"&gt;
Este documento explica cómo hacer lo siguiente:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Preparar tu "First Run Install" con los archivos propios de la aplicación.&lt;/li&gt;
&lt;li&gt;Instalar los ficheros .df1 en modo de sólo-lectura.&lt;/li&gt;
&lt;li&gt;Crear tu propio "package" (.pkg) de instalación.&lt;/li&gt;
&lt;li&gt;Colocar "script's" dentro del "package".&lt;/li&gt;
&lt;li&gt;Construir el "package", desde una opción de menú o mediante Cmd+B.&lt;/li&gt;
&lt;li&gt;Firmar el "package" resultante, para su distribución.&lt;/li&gt;
&lt;li&gt;Probar su carga/descarga, instalación y ejecución.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Antes debo explicarte que realmente existen dos tipos de firmas, una es la "Firma de la aplicación" (Application Signing) y la otra la "Firma del producto" (Product Signing). Ambos tipos pueden ser obtenidos tras registrarte como desarrollador en Apple. ($99 dólares anuales)&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
De modo que lo primero es convertirse en un desarrollador registrado, para después obtener su certificado. Hacerlo desde Xcode es más fácil que hacerlo manualmente desde la web, pero de todos modos se trata de un proceso realmente sencillo.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ahora te contaré cómo se hace, si el caso es que no vas a usar Xcode. Lo primero es, que tendremos que hacer uso de tu cuenta en Apple, esa misma que usas para comprar cosas en iTunes o en la App Store. Si no tienes una, tendrás que registrarse para obtenerla.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Lo primero será iniciar sesión con tu cuenta de Apple. Una vez allí, localiza el enlace al "Programa de Desarrolladores" (Developer Program) o al de "Desarrollador Registrado" (Registered Developer). Una vez allí podrás realizar el registro como nuevo desarrollador Apple. Una vez completado el proceso, (es posible que la nueva cuenta tarde un poco en activarse) podremos solicitar certificados.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Localiza el enlace a Certificados (Certificates). Desde aquí podrás solicitar certificados, indicándote también cómo proceder. Observarás que se hace uso del "Keychain Access" (Acceso a llaveros) durante la creación de certificados. Observa también que la página web muestra un menú en la esquina superior izquierda, donde figuran en primer lugar dispositivos iOS, deberemos cambiarlo a MacOS para obtener así el certificado correcto.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Una vez seleccionado MacOS podrás ver sus opciones. Deberemos escoger aplicaciones o instaladores que no estarán en la tienda de aplicaciones (App Store). A partir de ahí, verás que debes elegir entre un certificado para aplicaciones que están en desarrollo o para las ya en producción, elige producción (Production). Luego verás que tienes que elegir entre aplicaciones (Applications) o instaladores (Installers). Elige instalador, porque es el que necesitamos para firmar nuestro .pkg.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Descubre que en la parte inferior de la página, hay un lugar donde hacer clic para obtener un "Certificado Intermedio" (Intermediate Certificate). Este también es necesario, ya que causa que los demás se ejecuten correctamente. Así que obtén el denominado "WW Developers", sin marcar la opción "CA Authority".&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ahora descubrirás que necesitas generar un "Cert. request" desde el "Keychain Access" de tu Mac, después tendrás que subirlo a la web de Apple, para finalmente poder descargar nuestro certificado. Lo que se descarga es un certificado digital que deberás instalar también en el "Keychain Access" de tu Mac, para esto, bastará con hacer doble clic sobre el certificado que acabas de descargar.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Haz que tus certificados se carguen al inicio de sesión (Login Keychain), es una de las tres opciones que se muestran en la ventana tras el dobre-click. También el propio "Keychain Access" muestra un pequeño menú en la esquina superior izquierda, desde el que poder elegir "Login keychain" para el nuevo certificado.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Los certificados se guardan en el "Keychain Access" y son necesarios para verificar tu identidad. Al fin y al cabo, se trata de poner tu firma en tus productos de modo que otros puedan verificar su procedencia.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Una vez que tengas los dos certificados instalados, estarás listo para firmar los instaladores (Productos). Realmente lo único que los desarrolladores de Omnis necesitamos en este momento es la firma de instalador (Installer). Pero también podemos volver a firmar la aplicación Omnis.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Por aplicación, debemos entender una copia completa del paquete Omnis instalado, que lleva la extensión ".app". Mientras que por instalador debemos entender que se trata de un "Package" con extensión ".pkg" y no de orto tipo de instaladores más sofisticados de los que guían al usuario durante la instalación, mientras le muestran algunas imágenes.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Realmente a un desarrollador Omnis (de momento) le vastará con preocuparse por firmar su instalador, y añadir alguna que otra secuencia de comandos que permita ajustar después de la instalación algunas propiedades y cambiar algunos permisos.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En este momento, Apple no obliga a que la aplicación tenga el código firmado para poder ejecutarse, si el caso es que se instala desde un paquete firmado, ten en cuanta que si firmas la aplicación, no podrás cambiar nada dentro de ella sin volver a firmarla. Si alguna vez Apple requiere que la aplicación esté firmada, los desarrolladores de Omnis tendremos que enviar instaladores completos.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La firma deberá llevarse a cabo desde la línea de comandos del terminal y deberá realizarse una vez construido el instalador, este será modificado mediante el comando correspondiente, para incluir tu seña de identidad.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Omnis requiere de la ejecución de un "script" que corrija permisos y, en ocasiones, propiedades de todos los archivos contenidos en el paquete. Este script es muy simple, solo unas pocas líneas de código. La razón por la que debe ejecutarse tras la instalación es debido a que los permisos y las propiedades deben cambiarse, de otro modo el programa fallará y no podrá ejecutarse con normalidad. Crearemos un script para Omnis 4.3 y otro para Omnis Studio 8. Lo más probable es que el script para 8 también funcione para 10 y que el de 4 funcione para 5 y 6.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Para la creación del instalador o .pkg, usaremos "Packages" disponible en:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;a href="http://s.sudre.free.fr/Software/Packages/about.html"&gt;http://s.sudre.free.fr/Software/Packages/about.html&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
El botón de descarga se encuentra en la esquina superior derecha.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Primero, si tienes archivos ".df1", asegúrate de "Obtener información" (Comando-I) de cada uno de ellos, para marcarlos "Todos" con acceso de "Lectura/Escritura" y situarlos bajo "First Run Install" si se usa.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Después crearemos nuestro "package", simplemente mediante colocar los elementos a instalar sobre el área "Payload" (Carga útil) de "Packages". Ten en cuenta que si quieres que algo quede situado sobre el nivel raíz del disco duro, deberás arrastrarlo a la parte superior, hasta que veas que la línea se desplaza totalmente hacia la izquierda, luego la sueltas, junto a otras posibles cosas que también se deban encontrar en ese mismo nivel.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ten en cuenta que pueden existir carpetas ocultas. Para verlas, busca en uno de los menús la opción "Show hidden folders". Esto mostrará, (entre otras cosas) una carpeta "fonts" que podrás usar para instalar fuentes... simplemente colócalas con sangría debajo del nombre de esa carpeta, debajo de "fonts" y se instalarán correctamente.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Entra en "Packages Destination" y selecciona la carpeta "First Run Install" de Omnis y su destino, puedes colocar los archivos donde quiera que vayan. Algunos estarán a su vez, en otras carpetas dentro de "First Run Install", la cual es a su vez es una carpeta dentro de Omnis (para localizarla, haz clic con el botón derecho sobre Omnis y "Mostrar contenido del paquete" - luego "Contents", después "MacOS", y encontrarás la carpeta "First Run Install"). Dentro de ésta es donde deberás poner todas tus cosas. Cuando el usuario ejecute Omnis por primera vez, todos su contenido será copiado en los destinos mencionados.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cuando ya tengas colocados todos los ficheros y carpetas en el lugar que le corresponden dentro de Omnis, deberemos colocar el propio Omnis y cualquier otra cosa que necesitemos en el área "Payload" (Carga útil) de "Packages", de éste modo estaremos listos para construir nuestro paquete. Observa que dispones de muchas opciones, pero ninguna de ellas necesaria durante la construcción de un paquete básico como el nuestro. Claro que no es imprescindible hacer todo esto para instalar una aplicación, pero el uso de "Packages" proporcionará al usuario una experiencia de instalación más profesional.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Una vez que creado, podremos ver un pequeño ícono de caja y será ahora cuando deberemos proceder con el proceso de firma del Producto (Product Sign) mediante comandos de Terminal, después lo probaremos, comprobaremos que podemos cargarlo/descargarlo, que el proceso de verificación "Apple Gatekeeper", funciona correctamente y que la aplicación Omnis puede ser ejecutada sin problemas.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Un truco para ahorrarnos trabajo en el terminal, consiste en arrastar cualquier archivo sobre la ventana de éste, para así obtener la ruta hacia el mismo ya escrita sobre la línea de comandos.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Otra forma de hacerlo es escribiendo la ruta entre comillas dobles, para no necesitar escapar de los espacios u otros caracteres especiales. Por ejemplo escribiendo:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
"/Users/Das's/Desktop/JyotishStudio4.pkg"&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Algunos comandos de Terminal solicitarán tu contraseña, si te aparece un pequeño candado como cursor en el Terminal, significará que debes escribir tu contraseña de administrador para completar el comando. En algunos casos, puede que se te muestre un cuadro de diálogo solicitando esta misma contraseña.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Aquí está el comando que debes usar para firmar el "Package":&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
productsign --sign "Developer ID Installer: Das Goravani" /Users/Das\'s/Desktop/build/JyotishStudio4.pkg /Users/Das\'s/Desktop/JyotishStudio4signed.pkg&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Realmente el comando consiste en la primera parte solamente, hasta el nombre del desarrollador. El resto son DOS rutas. LA PRIMERA es la ruta hacia el paquete que queremos firmar, sólo UN ESPACIO la separa del nombre del desarrollador y de la segunda ruta indicada. La segunda ruta corresponde a un nuevo archivo que se creará. Será un duplicado de nuestro paquete pero con la firma incluida. El original permanecerá coo estaba.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Si has escrito todo correctamente, al presionar retorno, se firmará tu aplicación y se creará el nuevo archivo cono nuestro instalador ya firmado. Ahora todo lo que queda resta, es probarlo, cosa que puedes hacer de inmediato, cono sólo hacer doble clic sobre él o bien empezar por subirlo a algún sitio para después descargarlo y luego instalarlo.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Su ejecución no será exitosa, a menos que pongamos antes nuestro "Post Process Script". El script deberemos ubicarlo (como ya hemos indicado) desde el programa "Packages" en el apartado "Post Install" pestaña "Scripts". Podemos simplemente arrastrarlo, para soltarlo sobre "Post Install" para ver su icono allí.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
El "script" necesario para Omnis 4, 5 o 6, sería el siguiente:&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
#!/usr/bin/env bash&lt;br /&gt;# Este script se ejecuta una vez instalada la aplicación.&lt;br /&gt;# Indica la ruta hacia tu aplicación&lt;br /&gt;APPLICATION_ROOT="/Jyotish Studio 4.0/JS4.app"&lt;br /&gt;# Estabece permisos&lt;br /&gt;sudo chown -R root:admin "${APPLICATION_ROOT}"&lt;br /&gt;sudo chmod -R 775 "${APPLICATION_ROOT}"&lt;/blockquote&gt;
&lt;div style="text-align: justify;"&gt;
Crea un documento de TEXTO PLANO, con estas líneas y guárdalo, para después añadirlo a tu instalador como ya se ha descrito. Se ejecutará después de la instalación, establecerá todos los permisos y propiedades haciendo que el programa se ejecute correctamente.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Para Omnis 8:&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
#!/usr/bin/env bash&lt;br /&gt;# Este script se ejecuta una vez instalada la aplicación.&lt;br /&gt;# Indica la ruta hacia tu aplicación&lt;br /&gt;APPLICATION_ROOT="/Applications/Omnis Studio Runtime 8.0.2 x64.app"&lt;br /&gt;# Estabece permisos&lt;br /&gt;sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/startup"&lt;br /&gt;sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/icons"&lt;br /&gt;sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/iconsets"&lt;br /&gt;sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/local"&lt;br /&gt;sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/omnispdf"&lt;br /&gt;sudo chmod -R a+rw "${APPLICATION_ROOT}/Contents/MacOS/studio"&lt;br /&gt;# Para Brainy Data's PDFDevice (omitir si no se usa)&lt;br /&gt;sudo chmod a+rw ../MacOS&lt;/blockquote&gt;
&lt;div style="text-align: justify;"&gt;
Quiero dar las gracias en especial a Das Goravan, Paul Mulrooney y Alex Clay por el trabajo realizado y su aportación a éste documento.&lt;/div&gt;
</description><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Firmado y localización de aplicaciones (Parte 1 de 3)</title><link>http://framosmu.blogspot.com/2019/03/firmado-y-localizacion-de-aplicaciones.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Fri, 8 Mar 2019 14:34:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-1654573320755543541</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih9LbunQ7BEB7osgQzSiNGJAQtqxHgnHpL2-scjUx9dH5qmY27Ni5eFLJTDs9_7TA04pqtiNrn51AwilMze62sK7t4rlSeXBmDxS5TUvFid7Y7Oux_nOT5bpm3OL_piFrM6UYd/s1600/images.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="183" data-original-width="275" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih9LbunQ7BEB7osgQzSiNGJAQtqxHgnHpL2-scjUx9dH5qmY27Ni5eFLJTDs9_7TA04pqtiNrn51AwilMze62sK7t4rlSeXBmDxS5TUvFid7Y7Oux_nOT5bpm3OL_piFrM6UYd/s400/images.jpeg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
El núcleo de nuestra aplicación final Omnis Studio resultante para MacOS, es código firmado, lo cual proporciona mayor seguridad y confianza a los destinatarios finales de nuestras aplicaciones. La firma proporciona una garantía de que nosotros (como desarrolladores) somos los creadores del software que el usuario se está instalando en sus equipos, sin que éste haya sufrido alteración alguna desde su compra, por lo tanto, garantiza la autenticidad de una aplicación. Otra ventaja (no menos importante) de las aplicaciones firmadas dentro macOS, es que se les puede conceder permisos de forma automática para realizar acciones, tales como el acceso a servicios red, la ejecución de software auto-contenido o generado por la propia aplicación, como comandos AppleScript, Node.js, etc.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Una aplicación sólo puede ser firmada si su núcleo de código se mantiene sin cambios. En el caso que nos ocupa, (nuestras aplicaciones Omnis Studio) dicho núcleo se encuentra en el "Omnis package", por ejemplo:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;Omnis Studio &amp;nbsp;10.0.app/Contents/MacOS/&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Las carpetas "Firstruninstall" y "Application Support"&lt;/h3&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
El resto de archivos susceptibles de ser modificados desde dicho núcleo de código Omnis, y que &amp;nbsp;también forman parte de nuestra aplicación terminada, (como por ejemplo nuestras librerías) deberán &amp;nbsp;ser reubicados como datos de la aplicación para el/los usuario/s en sus directorios de trabajo particulares, es decir, en sus carpetas "Application Support":&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;~/Library/Application Support/Omnis/&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Para ello y cuando el usuario ejecuta por primera vez, nuestra aplicación Omnis, se comprobará la existencia de una carpeta denominada "&lt;b&gt;firstruninstall&lt;/b&gt;" dentro del&amp;nbsp;"Omnis package". Cualesquiera archivos contenidos en esta carpeta serán copiados en otra dentro del "Application Support"&amp;nbsp;con el nombre asignado al "Omnis package", por ejemplo:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;~/Library/Application Support/Omnis/MiAplicacionOmnis&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
o&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;~/Library/Application Support/Omnis/Omnis Studio 10.0&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La copia no se realizará, si la carpeta de destino ya existe, evitándose así la perdida accidental de cualquier cambio realizado posteriormente. Si la carpeta es eliminada, cambiada de nombre o lugar, será copiada nuevamente tras la ejecución de nuestra aplicación, pero con su contenido inicial.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La idea más interesante de éste modo de funcionamiento, es la de permitirnos (a los desarrolladores) colocar todos los archivos y carpetas requeridos por nuestro "runtime-omnis" y que conforman nuestra aplicación terminada, (como por ejemplo, las carpetas: "icons", "studio", "startup" e incluso una posible carpeta "xcomp" y/o "jscomp", con extensiones no incluidas en el núcleo Omnis) en la carpeta 'firstruninstall', creándose así un procedimiento de instalación de nuestra a aplicación al usuario final.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Una vez realizada la copia en el "Application Support" Omnis sólo actualizará los archivos contenidos en ese lugar dejando la carpeta original "macOS" sin cambios y por tanto con su firma válida.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;i&gt;&lt;b&gt;¿Qué ocurre si necesito actualizar o añadir algún componente ubicado en "xcomp" o "jscomp"?&lt;/b&gt;&lt;/i&gt;&lt;/h3&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Puesto que la aplicación está firmada, cualquier componente externo deberá ser añadido o actualizado en la carpeta de datos del usuario. Esto permite que la parte de código firmada permanezca inalterable. De modo que, cualquier componente externo podrá colocarse en:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;~/Library/Application Support/Omnis/Omnis Studio 10.0/xcomp&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
o&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;~/Library/Application Support/Omnis/Omnis Studio 10.0/jscomp&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Si no existe la carpeta requerida podrá ser creada por el usuario. Omnis, siempre cargará primero los archivos contenidos de la carpeta del usuario y después los de su propio núcleo Omnis, si el componente a cargar ya existe, (es decir fue cargado desde la carpeta del usuario) será ignorado, &lt;b&gt;la carpeta del usuario siempre tiene prioridad&lt;/b&gt;.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;i&gt;&lt;b&gt;¿Qué debo hacer para personalizar la instalación de mi aplicación y cambiar la firma?&lt;/b&gt;&lt;/i&gt;&lt;/h3&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En el momento de distribuir nuestra propia aplicación, deberemos primero actualizar los archivos incluidos en el "Omnis package" a fin de que contenga nuestras librerías, nuestros componentes y nuestro propio nombre de aplicación (no desearemos que se llame Omnis). Estos archivos deberán ser colocados en la carpeta "firstruninstall", los cuales serán tratados como datos del usuario y por tanto serán copiados a la carpeta "Application Support". NOTA: Para el sistema "Windows" existe un procedimiento similar a éste, pero no es objeto de éste artículo.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Por defecto, los datos de usuario para cada instalación de una aplicación Omnis, estarán ubicados en una sub-carpeta de "Application Support" denominada “Omnis” y el nombre del "Omnis package" será el utilizado para denominar a la carpeta de nuestra instalación en particular.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
Por ejemplo, para un "Omnis package" con el nombre... &lt;span style="color: blue;"&gt;/Applications/Omnis Studio 10.0.app&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
...sería:&amp;nbsp;&lt;span style="color: blue;"&gt;~/Library/Application Support/Omnis/Omnis Studio 10.0&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
..y para un "Omnis package" con el nombre... &lt;span style="color: blue;"&gt;/Applications/MiAplicacionOmnis.app&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
...sería:&amp;nbsp;&lt;span style="color: blue;"&gt;~/Library/Application Support/MiAplicacionOmnis&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Para personalizar la sub-carpeta, podremos editar recurso 25599, y para personalizar la carpeta de instalación, el 25600. Ambos recursos se encuentran en el archivo "localizable.strings" para el idioma en uso, por ejemplo:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;/Omnis Studio 10.0.app/Contents/Resources/English.lproj/Localizable.strings&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
o&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="background-color: white;"&gt;&lt;span style="color: blue;"&gt;/Omnis Studio 10.0.app/Contents/Resources/Spanish.lproj/Localizable.strings&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ambas entradas están vacías, permitiéndose así, su comportamiento por defecto.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;"CORE_RES_25599" = "";&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;"CORE_RES_25600" = "";&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Una vez actualizados y ubicados éstos archivos, el paquete Omnis, tendrá que ser vuelto a firmar, con nuestra propia identidad firma. No es posible volver a firmar un archivo que ya está firmado, por lo que la firma anterior deberá ser eliminada antes de volver a firmar. Esto lo haremos de forma recursiva, &amp;nbsp;a fin de que afecte a todo el "Omnis package" mediante el siguiente comando:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue;"&gt;xattr -r -d com.apple.FinderInfo &lt;package_path&gt;&lt;/package_path&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Por ejemplo:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="color: blue;"&gt;xattr -r -d com.apple.FinderInfo /Applications/MiAplicacionOmnis.app&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Naturalmente la firma pertenece al propietario de la aplicación y por tanto se requiere de una "identidad para la firma de código", desde donde generar y añadir el correspondiente certificado en su modalidad "development" o "production", sino dispone de una podrá obtenerla desde el "Apple developer member center" en su sección "Certificate". Para realizar la firma, el equipo desde el que esté haciéndolo, deberá tener instalados tanto el certificado, como su clave privada. Para comprobar si dispone de una firma de código válida en su&amp;nbsp;equipo, utilice el siguiente comando desde el terminal:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue;"&gt;security find-identity -p codesigning -v&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Por ejemplo, producirá la siguiente salida donde se muestra su "key" e "identity":&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: x-small;"&gt;1) 44FFBA8B7DFFB1AFFF36FD0613D6E5FC61FF8DFF "Certificate" (CSSMERR_TP_NOT_TRUSTED)&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: x-small;"&gt;2) B3EF62FF18E0FFB83D3A8FF3672CF80EFF367FFF "Mac Developer: John Doe (24FFEXFF39)"&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: x-small;"&gt;2 valid identities found&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Para finalmente firmar el "Omnis package" use:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="color: blue;"&gt;codesign -f --deep --verbose -s &lt;identity&gt; &lt;package_path&gt;&lt;/package_path&gt;&lt;/identity&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Por ejemplo:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue;"&gt;codesign -f --deep --verbose -s "Mac Developer: John Doe (24FFEXFF39)" /Applications/MiAplicacionOmnis.app&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
Si todo ha ido bien, podrá ver sobre el terminal una línea similar a la siguiente:&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue;"&gt;:signed app bundle with Mach-O thin (x86_64) [com.myCompany.MyApplication]&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
De éste modo su aplicación estará firmada y lista para su despliegue, sólo debe ser consciente de que no alterar posteriormente el contenido del "&lt;span style="text-align: justify;"&gt;Omnis package&lt;/span&gt;" ya que esto anularía la firma. Si desea verificar la firma use el siguiente comando:&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue;"&gt;codesign --display --verbose=4 &lt;package_path&gt;&lt;/package_path&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
La salida de éste comando incluirá información como la autoridad de firma, caducidad, etc.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;i&gt;¿Qué ocurre si necesito actualizar el núcleo de Omnis de mi aplicación final?&lt;/i&gt;&lt;/h3&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Si desea distribuir una actualización del núcleo Omnis (el archivo de programa), sustituyendo el actualmente firmado, deberá hacer lo siguiente:&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Reemplazar el binario Omnis original firmado por la nueva versión.&lt;/li&gt;
&lt;li&gt;Volver a firmar Omnis con la misma identidad de firma que utilizó para el original.&lt;/li&gt;
&lt;li&gt;Usar el binario parcheado de su directorio para su distribución.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Tenga en cuenta que los componentes y otros archivos del usuario pueden ser actualizados sin necesidad de volver a firmar el paquete, ya que las carpetas "xcomp" y "jscomp" residen en la ubicación de datos de usuario, por ejemplo:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="color: blue; text-align: left;"&gt;~/Library/Application Support/MiAplicacionOmnis&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Asegúrese siempre de que el núcleo Omnis que está ejecutando, posea una firma válida mediante el comando:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="color: blue;"&gt;codesign --display --verbose=4&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue; text-align: left;"&gt;&lt;package_path&gt;&lt;/package_path&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih9LbunQ7BEB7osgQzSiNGJAQtqxHgnHpL2-scjUx9dH5qmY27Ni5eFLJTDs9_7TA04pqtiNrn51AwilMze62sK7t4rlSeXBmDxS5TUvFid7Y7Oux_nOT5bpm3OL_piFrM6UYd/s72-c/images.jpeg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Firmado y localización de aplicaciones (Parte 2 de 3)</title><link>http://framosmu.blogspot.com/2019/03/firmado-y-localizacion-de-aplicaciones_11.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Thu, 7 Mar 2019 10:20:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-1481775915862106103</guid><description>&lt;h3&gt;
&lt;span style="text-align: justify;"&gt;Personalización de las opciones en el menú del sistema macOS&lt;/span&gt;&lt;/h3&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;span style="text-align: justify;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx8McziaQP6S_NXcK0t6qctz6mUVIO8xrdlmzafJXvJlR52H8r-9be9QhHht9lVo0uYxhfhv4ghaVD99CXRnhd_wIFGacvf0tAHwCBuTUjBHV273xywf5IDn6fJiz0SRhRptwm/s1600/Imagen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="248" data-original-width="679" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx8McziaQP6S_NXcK0t6qctz6mUVIO8xrdlmzafJXvJlR52H8r-9be9QhHht9lVo0uYxhfhv4ghaVD99CXRnhd_wIFGacvf0tAHwCBuTUjBHV273xywf5IDn6fJiz0SRhRptwm/s640/Imagen.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Tras haber cambiado el nombre "Omnis" por el de nuestra propia aplicación, observaremos que el nombre del menú del sistema MacOS ahora presentará cómo título el nombre de nuestra aplicación, pero siguen apareciendo en él opciones cómo: "Hide Omnis", "Quit Omnis", "Preferences" o "Services" y que (con toda seguridad) desearemos personalizar para nuestra aplicación y según el idioma del usuario. No es el propósito de esta serie de artículos tratar el tema de la localización a otros idiomas de nuestras aplicaciones (tema ya tratado en éste blog) sino más bien, repasar los elementos que permiten la adecuada adaptación de nuestros "runtime-omnis", en cuanto a la creación del paquete final de instalación, de modo que trataremos las llamadas "Studio String Table" (studio.stb) con éste único propósito.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Puesto que llegados a éste punto ya habremos cambiado el nombre del "Omnis app package" por el de nuestra propia aplicación, deberemos cambiar ahora la opciones de su menú principal a fin de que se adecuen a nuestro producto, mediante los pasos siguientes:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Abra el "Omnis Catalog" (pulse F9) de Omnis Studio para MacOS&lt;/li&gt;
&lt;li&gt;Seleccione la pestaña "String Tables" y haga clic derecho sobre "Built-in&amp;nbsp;strings"&lt;/li&gt;
&lt;li&gt;Introduzca los textos originales sobre la columna de la STRINGID y el texto a cambiar sobre la/s columnas correspondientes al idioma 'en', 'es_es', etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Podremos localizar textos específicos a traducir originales de Omnis Studio mediante la opción, "Find strings…" (botón derecho sobre "Built-in&amp;nbsp;strings"), arrastrando y soltando el texto localizado, desde la ventana "Find" sobre la columna "STRINGID", para después añadir su texto traducido.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cómo ya hemos mencionado, no es el propósito de éste artículo, mostrar como adaptar nuestras aplicaciones a diferentes idiomas, por lo que cuestiones, sobre cómo localizar los días de la semana, meses del año, separadores de caracteres, ordenamiento nacional, etc, tienen en Omnis sus utilidades específicas para éstos asuntos, pero no es nuestro objetivo ahora.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Sólo haremos un apunte en cuanto al comportamiento de Omnis, cuando cambiamos el atributo de idioma en sus preferencias ($language).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cuando cambiamos la propiedad "$language" Omnis la aplica de inmediato, por lo que no necesita &amp;nbsp;reiniciar la aplicación ni ninguna otra acción, pero en caso de que la base de datos de localización (la llamada omnisloc.df1) esté siendo compartida entre varios usuarios, el cambio de lenguaje, solo será efectivo tras el reiniciado de la aplicación.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Un pequeño apunte final a modo de recordatorio&lt;/h4&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La notación:&amp;nbsp;&lt;b&gt;$root.$prefs.$language&lt;/b&gt;, retorna el nombre del lenguaje actualmente en uso, el cual podemos (del mismo modo) cambiar con efecto inmediato.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La propiedad:&amp;nbsp;$&lt;b&gt;hascurrlangnationalsortorder&lt;/b&gt;, es una propiedad boleana exclusiva de los "df1" y accesible mediante (por ejemplo) "$root.$datas.mificherodf1.$hascurrlangnationalsortorder", si es "true" causará que el orden de clasificación se corresponda con el idioma actual.&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx8McziaQP6S_NXcK0t6qctz6mUVIO8xrdlmzafJXvJlR52H8r-9be9QhHht9lVo0uYxhfhv4ghaVD99CXRnhd_wIFGacvf0tAHwCBuTUjBHV273xywf5IDn6fJiz0SRhRptwm/s72-c/Imagen.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Firmado y localización de aplicaciones (Parte 3 de 3)</title><link>http://framosmu.blogspot.com/2019/03/firmado-y-localizacion-de-aplicaciones_43.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Wed, 6 Mar 2019 12:20:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-3126916978449057637</guid><description>&lt;div style="text-align: justify;"&gt;
En esta última parte de la serie, tan sólo incluir una punte sobre nuestras aplicaciones "serverless" para dispositivos móviles.&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx78dqW3bRtnN5Kjf5HhZvqaVv1QIXDT0VngLJMGuKPIGUX3IIk6-FOi9ighMd3sG1aKafbt1Ujc_c6EPCnu6U4HzT1KzYcEcPeV2Tj5NMmsd7yRlmYsGB5mOuxoZl8ZQdyHY3/s1600/Imagen2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="692" data-original-width="1600" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx78dqW3bRtnN5Kjf5HhZvqaVv1QIXDT0VngLJMGuKPIGUX3IIk6-FOi9ighMd3sG1aKafbt1Ujc_c6EPCnu6U4HzT1KzYcEcPeV2Tj5NMmsd7yRlmYsGB5mOuxoZl8ZQdyHY3/s640/Imagen2.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Como ya sabemos, cuando creamos aplicaciones que van a trabajar sin necesidad de conexión con un servidor y que serán instaladas en dispositivos tales cómo teléfonos o tabletas, hacemos uso de la propiedad "$serverlessclientstringtable" para especificar qué "string table" a utilizar junto con nuestro "SCAF", en ella indicamos el nombre del fichero ".tsv", que deberá usarse.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Un par de apuntes&lt;/h4&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Recordamos que podemos hacer referencia desde el modo "execut on client" al "string table" actual, mediante la función "stgettext()", y asignar textos mediante el prefijo "$st". Además, los métodos de ejecución en el servidor también pueden hacer uso de "stgettext()" para localizar textos en el entorno local del cliente, ya sea mediante la configuración regional recibida desde el dispositivo del cliente, o mediante lo indicado en la propiedad "$stringtablelocale". Teniendo esto en cuenta, indicar que, en caso de que no sea posible localizar la columna para el lenguaje indicado, en el "string table", "stgettext ()" va a retornar los valores que encuentre en la segunda columna de la tabla, sin importar en que idioma se encuentren.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Otro apunte (ya explicado en otro artículo de éste blog) tiene que ver en cómo traducir a diferentes idiomas, los mensajes estándar, que Omnis envía al cliente, mencionar que todos ellos están por defecto en idioma inglés, pero que desde la versión 6 de Omnis Studio, se nos proporciona un mecanismo mediante el cual localizar a cualquier idioma dichos mensajes.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
En la dirección https://developer.omnis.net/documentation/webdev/index.jsp podemos encontrar un listado de estos mensajes, aunque debemos tener en cuanta que muchos de ellos nunca llegarán a ser mostrados, ya que corresponden más a errores de programación que a fallos del sistema o la comunicación, por lo que no todos, deberán ser traducidos.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Para anular modificar cualquiera de los textos de error predeterminados, si se trata de una aplicación Web, bastara con incluir nuestra propia traducción en la página HTML que contiene el código JavaScript de cliente, pero para el caso que nos ocupa, deberemos colocar los textos en un archivo independiente.&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx78dqW3bRtnN5Kjf5HhZvqaVv1QIXDT0VngLJMGuKPIGUX3IIk6-FOi9ighMd3sG1aKafbt1Ujc_c6EPCnu6U4HzT1KzYcEcPeV2Tj5NMmsd7yRlmYsGB5mOuxoZl8ZQdyHY3/s72-c/Imagen2.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Uso de iconos en Omnis Studio (Parte 1 de 2)</title><link>http://framosmu.blogspot.com/2019/03/uso-de-iconos-en-omnis-studio-parte-1.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Tue, 5 Mar 2019 11:05:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-2756092063065891126</guid><description>&lt;div style="text-align: justify;"&gt;
Desde la versión 8.0.1 de Omnis Studio, disponemos de un nuevo procedimiento para la incorporación de iconos a nuestras librerías, denominado "Iconset Studio" y ubicados bajo la carpeta "inconsets", dentro de la cual podremos indicar las sub-carpetas donde localizar los iconos con los que trabajaremos en nuestra librería. Ahora cuando hagamos referencia a un icono para su uso con cualquier componente (por ejemplo, mediante asignar la propiedad "$iconid" de un componente "button"). Nuestra librería lo buscará automáticamente en todo el conjunto "Iconset Studio", según la ruta especificada por nosotros mediante la propiedad "$iconset", o en cualquier otra ubicación para iconos. El orden de búsqueda ahora queda establecido del modo siguiente:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi08699Ydcy2VwX21lgCp6DYbK3qm7Rg0VY0k-VXpUOsMYtTls5cqJTG3vhQ0d-BwtbwTtpluQ4X9CN5nZexMxktivdE86uuHx5pU41h3kiVMqO8p9FE4oBzaKL2fSW0AZG-tto/s1600/main_components.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="215" data-original-width="345" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi08699Ydcy2VwX21lgCp6DYbK3qm7Rg0VY0k-VXpUOsMYtTls5cqJTG3vhQ0d-BwtbwTtpluQ4X9CN5nZexMxktivdE86uuHx5pU41h3kiVMqO8p9FE4oBzaKL2fSW0AZG-tto/s400/main_components.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;En el "Iconset Studio" personalizado para nuestra librería, una sub-carpeta de "inconsets", ruta indicada en su propiedad "$iconid".&lt;/li&gt;
&lt;li&gt;En la tabla #ICONS de nuestra librería. (si existe)&lt;/li&gt;
&lt;li&gt;En los archivos de datos para iconos, los llamados ".df1", excepto "omnispic" y "userpic", (si existen)&lt;/li&gt;
&lt;li&gt;En la sub-carpeta denominada "studio" situada dentro de "inconsets"&lt;/li&gt;
&lt;li&gt;En los archivos "Omnispic.df1" y "Userpic.df1".&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
El cuadro de diálogo "Select Icon", (que se muestra tras hacer clic en "$iconid" desde el "Property Manager") permite seleccionar un icono para nuestro componente, ahora mostrará los ubicados en "studio" y en la carpeta indicada mediante la propiedad "$iconset" de nuestra librería, (si se especifica).&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Un apunte que añadir a éste nuevo concepto, es que la carpeta "html/icons" tambien es compatible con el "Iconset Studio", pero se espera que poco a poco, todos los conjuntos de iconos sean ubicados bajo el directorio "/iconsets" localizable bajo el directorio principal de instalación Omnis.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Ahora podremos crear íconos HD desde cualquier software para la edición de imágenes y colocarlas directamente en el directorio Omnis, en la carpeta "inconsets". El icono o los archivos de imagen deben guardarse utilizando el tipo de archivo PNG y colocarse en una subcarpeta de "inconsets". Cada subcarpeta representa lo que se llama un "Iconset Studio", que es una colección de iconos con nombre. El nombre de la sub-carpeta se convierte en el nombre del "Iconset Studio" que luego aparecerá en el cuadro de diálogo de selección de iconos y cuya ruta es especificada bajo la propiedad "$iconset", de nuestra librería.&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Deberemos tener en cuenta que un "Iconset Studio" no puede denominarse igual que uno de nuestros "datafile" de iconos, o mediante alguno de los nombres reservados: "lib", "studio" o "studioide".&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Mas adelante publicaré un artículo en este blog, explicando como crear y usar imágenes, teniendo en cuanta los diferentes tamaños (16x16, 32x32, 48x48) y resoluciones para soportar los monitores "retina" (_2x, _15x, etc)&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Es posible que queramos utilizar algunos de los iconos actualmente ubicados en los archivos de datos o bien agregar o reemplazar algunos de ellos con versiones de mayor resolución. Para permitirnos exportar los existentes, se dispone de una herramienta en el menú "Tools&amp;gt;&amp;gt;Add Ons", denominada "JS Icon Export", disponible desde el cuadro de diálogo "Web Client Tools" (desplácese hasta el final de la lista "Web Client tools").&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La herramienta ‘JS Icon Export’ exportará todos los iconos contenidos del archivo seleccionado y los colocará en una sub-carpeta de "iconsets", aplicando los nombres de archivo correctos. Tenga en cuenta que (tras esto), la propiedad "$iconid" de un control, ahora hará referencia al archivo externo y no a la imagen en el archivo de datos y que Omnis ahora buscará los iconos, según el orden que ya hemos mencionado.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Si el mismo conjunto de iconos es incluido en otra carpeta, (después de que se haya encontrado) se ignoraran las carpetas subsiguientes y se escribirá un error en "iconsetlog.txt", ubicado en la carpeta "Studio".&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Si se está usando un servidor omnis web, todos los conjuntos de iconos deberán estar en la carpeta "html/icons" del servidor web.&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi08699Ydcy2VwX21lgCp6DYbK3qm7Rg0VY0k-VXpUOsMYtTls5cqJTG3vhQ0d-BwtbwTtpluQ4X9CN5nZexMxktivdE86uuHx5pU41h3kiVMqO8p9FE4oBzaKL2fSW0AZG-tto/s72-c/main_components.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Uso de iconos en Omnis Studio (Parte 2 de 2)</title><link>http://framosmu.blogspot.com/2019/03/uso-de-iconos-en-omnis-studio-parte-2.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Mon, 4 Mar 2019 12:13:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-5844469688243507862</guid><description>&lt;div style="text-align: justify;"&gt;
Importante indicar en primer lugar, que los procedimientos que permite guardar iconos en #ICONS o en archivos (como “Omnispic”) asignándoles un ID ($iconid), por compatibilidad hacia atrás, continúan funcionando, pero ahora sólo resultarán útiles con iconos en 16x16 pixeles. Debemos tener en cuenta, que si nuestras aplicaciones son ejecutadas en una pantalla HD y nuestras librerías aún usan éste tipo de iconos, Omnis intentará localizar un ícono correspondiente en 32x32, de no existir se usará la imagen 16x16 pero su apariencia visual resultará muy pobre. Para conseguir que sus antiguos iconos 16x16 se vean bien en alta definición, deberá crear una nueva versión de cada imagen a 32x32 píxeles e importar cada una de ellas al archivo de datos o #ICONS, bajo la sección 32x32 que encontrará en la misma página de iconos, usando los mismos identificadores o ID, que los usados con la versión 16x16.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ccGPYl72bpivkyK99im4tE-oYSDDvAGdBM4JD9-_jqc61edYMrtmrBhKwLE1FFk6EMr590mfplfZyyP-kg0Manr4KSOKJzOeQ3LOaJ7sk7e7pgIcdAiezVdlfvtwY3oDb4EC/s1600/page115image21430480.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="132" data-original-width="717" height="117" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ccGPYl72bpivkyK99im4tE-oYSDDvAGdBM4JD9-_jqc61edYMrtmrBhKwLE1FFk6EMr590mfplfZyyP-kg0Manr4KSOKJzOeQ3LOaJ7sk7e7pgIcdAiezVdlfvtwY3oDb4EC/s640/page115image21430480.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Si ha estado ya utilizando iconos en 32x32 o 48x48 píxeles en sus librerías y lo que quiere es que se vean correctamente en pantallas HD, deberá adaptar sus actuales librerías para su uso con el nuevo “Iconsets Studio”, lo cual implica disponer de archivos de imagen separados y ubicados en carpetas, las cuales permiten la inclusión de imágenes para iconos de hasta 96x96 píxeles (es decir, 2 veces el tamaño del icono más grande el de 48x48. Los “iconsets” son compatibles tanto con las clases “remote-form”, como con las habituales clases “window”, pero no podrán usarse con los antiguos plug-in ”’Web Client”, e 'iOS Client’.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Denominación de archivos imagen&lt;/h3&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cada archivo de imagen dentro de un conjunto de iconos, deberá seguir la siguiente convención:&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="color: #3e511e; font-family: Arial; font-stretch: normal; line-height: normal; margin-left: 8.6px; text-align: center; text-indent: -0.2px;"&gt;
&lt;span style="-webkit-font-kerning: none;"&gt;&lt;b&gt;texto_id_tamañoyestado_resolución.png&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="color: #3e511e; font-family: Arial; font-stretch: normal; line-height: normal; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;"&lt;b&gt;texto&lt;/b&gt;" Es el nombre de la imagen. Aparecerá en el cuadro de diálogo del selector de iconos, mientras asigna el “$iconid” de un objeto.&lt;/li&gt;
&lt;li&gt;"&lt;b&gt;id&lt;/b&gt;" es el ID (valor entero positivo) utilizado como ID del icono. Deberá estar en el rango de 1 a 10.000.000&amp;nbsp;&lt;/li&gt;
&lt;li style="text-align: justify;"&gt;"&lt;b&gt;tamaño&lt;/b&gt;" es el tamaño expresado en píxel CSS de la imagen independiente de su resolución, lo que significa que éste valor no cambiará, para con todas sus diferentes resoluciones. &lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Su valor debe ser expresado en la forma “&lt;ancho&gt;x&lt;alto&gt;”, los valores 16x16, 32x32 y 48x48 deberán existir siempre, ya que corresponden a los tamaños estándar admitidos por Omnis.&lt;/alto&gt;&lt;/ancho&gt;&lt;/li&gt;
&lt;li&gt;"&lt;b&gt;resolución&lt;/b&gt;" es el factor que identifica su densidad de píxeles, la cual deberá expresarse del modo siguiente: &amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;"_ 2x" para dispositivos HD o pantalla Retina.&lt;/li&gt;
&lt;li&gt;"_15x" para ciertos dispositivos, como por ejemplo teléfonos con una densidad de píxeles de 1.5x. no será necesario especificar valor alguno para dispositivos con una resolución estándar, o equivalente a _1x&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;div&gt;
Los archivos (o nombres de carpetas) que no cumplan con las convenciones especificadas serán ignorados.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Ejemplos válidos de nombres de archivo son:&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;table cellpadding="0" cellspacing="0" style="border-collapse: collapse;"&gt;&lt;tbody&gt;
&lt;tr&gt; &lt;td style="border-color: #000000 #000000 #000000 #000000; border-style: solid; border-width: 1.0px 1.0px 1.0px 1.0px; padding: 1.0px 1.0px 1.0px 1.0px; width: 328.6px;" valign="middle"&gt;&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-bottom: 12px; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;span style="font-kerning: none;"&gt;pencil_1657_16x16.png&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;/td&gt; &lt;td style="border-color: #000000 #000000 #000000 #000000; border-style: solid; border-width: 1.0px 1.0px 1.0px 1.0px; padding: 1.0px 1.0px 1.0px 1.0px; width: 448.4px;" valign="middle"&gt;&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;/div&gt;
&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-bottom: 12px; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;span style="font-kerning: none;"&gt;Icono con "estado"&amp;nbsp;&lt;estado&gt;normal, de tamaño 16x16, con ID 1657, para dispositivos con resolución estándar&lt;/estado&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/td&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td style="border-color: #000000 #000000 #000000 #000000; border-style: solid; border-width: 1.0px 1.0px 1.0px 1.0px; padding: 1.0px 1.0px 1.0px 1.0px; width: 328.6px;" valign="middle"&gt;&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;/div&gt;
&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-bottom: 12px; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;span style="font-kerning: none;"&gt;pencil_1657_16x16_2x.png&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;/td&gt; &lt;td style="border-color: #000000 #000000 #000000 #000000; border-style: solid; border-width: 1.0px 1.0px 1.0px 1.0px; padding: 1.0px 1.0px 1.0px 1.0px; width: 448.4px;" valign="middle"&gt;&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;/div&gt;
&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-bottom: 12px; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;span style="font-kerning: none;"&gt;Icono con "estado"&amp;nbsp;&lt;estado&gt;normal, de tamaño 16x16, con ID 1657, para dispositivos con resolución HD&lt;/estado&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/td&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td style="border-color: #000000 #000000 #000000 #000000; border-style: solid; border-width: 1.0px 1.0px 1.0px 1.0px; padding: 1.0px 1.0px 1.0px 1.0px; width: 328.6px;" valign="middle"&gt;&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-bottom: 12px; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;span style="font-kerning: none;"&gt;check_1658_32x32c_2x.png&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;/div&gt;
&lt;/td&gt; &lt;td style="border-color: #000000 #000000 #000000 #000000; border-style: solid; border-width: 1.0px 1.0px 1.0px 1.0px; padding: 1.0px 1.0px 1.0px 1.0px; width: 448.4px;" valign="middle"&gt;&lt;div style="font-family: Arial; font-size: 12px; font-stretch: normal; line-height: normal; margin-bottom: 12px; margin-left: 8.6px; text-align: justify; text-indent: -0.2px;"&gt;
&lt;span style="font-kerning: none;"&gt;Icono con estado&amp;nbsp;&lt;estado&gt;“c”, de tamaño 32x32, con ID 1658, para dispositivos con resolución HD (ver más abajo lo que significa su "estado"&lt;estado&gt;)&amp;nbsp;&lt;/estado&gt;&lt;/estado&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt; &lt;/table&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Se deberá tener en cuenta que los nombres de los archivos de imagen no distinguen entre mayúsculas y minúsculas y deben ser únicos para con todas la plataformas y sistema de archivos (los nombres repetidos serán ignorados).&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
Iconos para casillas de verificación&lt;/h3&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Como caso especial, es posible implementar iconos que permiten diferentes estados, tales como casillas de verificación y botones-radio.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;"&lt;b&gt;estado&lt;/b&gt;" es el estado en que se encuentra el icono (“marcado”, “resaltado” o “normal”) y puede ser uno de los siguientes: (dejarlo en blanco indica su estado “normal”).&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;“c” corresponde a la situación de “marcado” del icono&lt;/li&gt;
&lt;li&gt;“h” corresponde a la situación de “resaltado” del icono&lt;/li&gt;
&lt;li&gt;“x” corresponde a la situación de “marcado” y “resaltado” del icono&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div style="text-align: justify;"&gt;
Si no está seguro de que iconos necesitará crear y cual será su denominación, puede optar por examinar los contenidos en la carpeta “iconsets/studioide”, aquí podrá encontrar archivos de imágenes de diferentes tamaños, tal y como son requeridos para su uso con Omnis Studio. Pero tenga en cuenta que no puede usar los iconos de esta carpeta, sin adquirir antes la licencia adecuada. Use un esquema de nombres similar a éste para con sus propias creaciones.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Imágenes escaladas&lt;/h3&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
No es estrictamente necesario crear una imagen del icono para cada una de las posibles resoluciones, aunque sería recomendable hacerlo si se desea obtener una mejor apariencia. No obstante Omnis puede hacer uso de la imagen que mas se acerque a la resolución deseada, escalando la misma, en éstos casos es mejor forzar a que sea el propio Omnis quien efectúese el escalado en lugar de hacerlo nosotros mismos. En estos casos, lo mejor será proporcionar a Omnis la imagen con la mayor resolución posible, para dejar que Omnis reduzca las imágenes de resolución más baja, pero tenga en cuenta que el escalado puede producir resultados no esperados.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cuando se produce una conexión (aplicaciones Web), el cliente envía su resolución al servidor de aplicaciones Omnis. Lo cual permite a Omnis hacer uso &amp;nbsp;del ícono apropiado.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Preguntas frecuentes&lt;/h3&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;b&gt;&lt;i&gt;¿Cómo hacer uso de Imágenes con tamaños “no estándar”?&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Naturalmente podemos disponer de imágenes de tamaño diferente al estándar (16x16, 32x32, 48x48) siempre y cuando incluyamos en su nombre de archivo las especificaciones de tamaño. Por ejemplo, podemos crear una imagen de 100x200 píxeles, nombrándola como "midibujo_1688_100x200.png", su versión en alta resolución (a 200x400 píxeles), tendría como nombre ”midibujo_1688_ 100x200_2x.png”, (esto sería equivalente a una “Icon Page” de Omnis )&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;b&gt;&lt;i&gt;¿Cómo agregar “Iconsets” al servidor de aplicaciones web?&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cuando se trate de una aplicación que queremos hacer disponible en la Web, necesitaremos copiar todos los “inconsets”utilizados en nuestros formularios desde el directorio “/iconsets” en de nuestra versión “developer” a la carpeta “/icons” situada al mismo nivel que nuestros archivos “.htm” de nuestra aplicación, es decir, en el lugar donde estén ubicados nuestros ficheros “.htm” en el servidor web: cada “iconsets” deberá aparecer como una sub-carpeta de la carpeta “/icons” y deberá contener todos los archivos PNG que precise nuestra aplicación.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;b&gt;&lt;i&gt;¿Cómo configuro mi librería para el uso de “inconsets”?&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Las librerías poseen una preferencia denominada “$iconset” ($libs.LIBRERIA.$Prefs) y es aquí donde deberá figurar el nombre del “iconset” que usaremos con nuestra librería, de éste modo Omnis sabrá dónde buscar los identificadores de nuestros iconos. En cada ocasión que trabajemos con esta librería, Omnis buscará los iconos dentro del “iconset” especificado para ella, antes de hacerlo en el resto de posible ubicaciones.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;b&gt;&lt;i&gt;¿Cómo gestiona Omnis los posibles errores al asignar un ID?&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Cualquier error causado al configurar el ID de un icono para los objetos, será enviado a un archivo de errores denominado “iconsetlog.txt” ubicado en la carpeta “html”.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;b&gt;&lt;i&gt;¿Puedo hacer uso de imágenes mediante la indicación de una URL?&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Al asignar el “$iconid” para un objeto bajo “jsClient”, podemos optar por indicar una URL. Si el valor asignado consiste en una cadena de caracteres que contiene al menos un carácter ”/“, Omnis lo tratará como una URL generada por la función “iconurl”, esto significa que podremos referenciar archivos de iconos alternativos, según las diferentes resoluciones de pantalla de los clientes, Omnis elegirá el icono correcto. En caso de hacerse la asignación mediante programación y siempre que el valor asignado no sea un ID de icono (un entero o un entero + una constante de tamaño), Omnis entenderá que se trata de una URL generada por la función “iconurl” eligiéndose el correspondiente a la resolución del cliente. Las URL’s que necesite podrán ser generadas mediante el uso de la función “iconurl()” en el método “$construct()” del “remote-form” y ser guardadas en una variable de tipo “list” en el ámbito de la instancia, con el fin de usarlas en el código que realice la asignación de imagen a los diferentes objetos.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;b&gt;&lt;i&gt;¿Cómo gestionar dinámicamente la asignación de imágenes, para (por ejemplo) un componente “tree lists”?&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Los “Tree control” de jsClient, han sido modificados, de modo que su columna “iconid” ahora es “iconurl”, y su propiedad “$iconurlprefix” ahora resulta redundante, aunque se sigue manteniendo por compatibilidad hacia atras. La columna “iconurl” deberá ser definida como de tipo carácter y rellenarse utilizando una función “iconurl(iconid)”, que devuelve una cadena URL con el nombre del archivo de imagen o bien una lista separada por punto y coma, con los nombres de los archivos en caso de iconos con varias resoluciones. Esto es lo que permite a Omnis elegir el icono correcto según la resolución de pantalla del cliente conectado.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ccGPYl72bpivkyK99im4tE-oYSDDvAGdBM4JD9-_jqc61edYMrtmrBhKwLE1FFk6EMr590mfplfZyyP-kg0Manr4KSOKJzOeQ3LOaJ7sk7e7pgIcdAiezVdlfvtwY3oDb4EC/s72-c/page115image21430480.jpg" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Nueva herramienta de migración de Omnis DF1 a SQLite o PostgreSQL</title><link>http://framosmu.blogspot.com/2018/10/nueva-herramienta-de-migracion-de-omnis.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><category>OMSQLDAM</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Fri, 28 Dec 2018 09:57:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-3960761916599604139</guid><description>&lt;div style="text-align: justify;"&gt;
Otra de las novedades que incluye Omnis Studio 10, supone una garantía de estabilidad y longevidad para nuestras aplicaciones, especialmente en lo que al uso de la base de datos nativa (los llamados df1) se refiere. La gran ventaja que supondrá el uso de ésta herramienta es, que&amp;nbsp;tras su conversión a una base de datos SQLite o PostgreSQL, los antiguos comandos denominados "Omnis DML" permanecerán en la biblioteca convertida, pero, (y este es el importante detalle) se ejecutarán contra la base de datos seleccionada (SQLite o PostgreSQL), sin problemas y automáticamente, en lugar del antiguo fichero de datos Omnis. Por ejemplo, comandos como "Prepare for edit" o "Update files" se ejecutaran contra la nueva base de datos (SQLite o PostgreSQL).&amp;nbsp;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIGGn_ZNa2taRdzQ4wpqEjzRp50p9lvwG1M7eQERXJL3z6jetELYTVQT-S60ARvY1Ttl1ISDEGpLgWUGQKphkXWgPOJf7Vh3XyoMfuI_cqeflgtSHPZ1d8DnL9lil-NqKb6M2Q/s1600/db2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="183" data-original-width="568" height="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIGGn_ZNa2taRdzQ4wpqEjzRp50p9lvwG1M7eQERXJL3z6jetELYTVQT-S60ARvY1Ttl1ISDEGpLgWUGQKphkXWgPOJf7Vh3XyoMfuI_cqeflgtSHPZ1d8DnL9lil-NqKb6M2Q/s640/db2.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Sin duda ésta opción, es muy bien recibida por todos aquellos que hemos deseado por mucho tiempo, disponer de un almacenamiento de datos más robusto, proporcionándonos a la vez, una cómoda puerta de salida, en la migración de nuestras antiguas aplicaciones hacia el soporte de código SQL. Un mejorado "OmnisSQL DAM" será el encargado de producir el "milagro" de acceder a un fichero SQLite como si se tratase de un antiguo fichero .df1&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Se han realizado pruebas con el nuevo "OmnisSQL DAM" contra archivos de datos SQLite y Omnis, tanto directamente como utilizando "Data Bridge". Las pruebas se han realizado insertando ~ 2.5MB y leyendo ~ 20MB de un archivo de datos. Los tiempos de finalización de la prueba se muestran en segundos.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmoSLTnjdsnUMUUUb7E37uthx8VktRCA5rVJWsrTYNM1GXKOdkA1q2asDULUA7SsMH_N5HilMsd-lLs4LSgYAt8GQipaKK-tqVyrSY3dcPNgajMj-UZxXZLC9OLrE3JE603CEJ/s1600/db1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="312" data-original-width="885" height="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmoSLTnjdsnUMUUUb7E37uthx8VktRCA5rVJWsrTYNM1GXKOdkA1q2asDULUA7SsMH_N5HilMsd-lLs4LSgYAt8GQipaKK-tqVyrSY3dcPNgajMj-UZxXZLC9OLrE3JE603CEJ/s640/db1.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIGGn_ZNa2taRdzQ4wpqEjzRp50p9lvwG1M7eQERXJL3z6jetELYTVQT-S60ARvY1Ttl1ISDEGpLgWUGQKphkXWgPOJf7Vh3XyoMfuI_cqeflgtSHPZ1d8DnL9lil-NqKb6M2Q/s72-c/db2.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Objetos "JavaScript Worker"</title><link>http://framosmu.blogspot.com/2019/02/objetos-javascript-worker.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Thu, 27 Dec 2018 09:20:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-4248621731284475368</guid><description>&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;Omnis Studio 10, ahora tiene embebido (integrado) el "&lt;span style="font-size: 11pt;"&gt;framework&lt;/span&gt;" "&lt;b&gt;node.js&lt;/b&gt;", el cual incluye gran cantidad de módulos de código abierto desarrollados por terceros y que (por tanto) podremos usar libremente desde nuestro código Omnis. Un nuevo "Worker Object" denominado "&lt;b&gt;JavaScript Worker Object&lt;/b&gt;" nos permitirá ejecutar métodos de "node.js", mediante simplemente invocarlo desde nuestro código Omnis, para posteriormente recibir los resultados en el método indicado como retorno del mismo. A modo de ejemplo, Omnis incluye la librería "xml2js" la cual permite convertir un XML a JSON.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiilek6nVNMeYsb7Q66aqf9CPo2HGdKAPnHRgACp5l2Pt7NWTZMDco2dVubwHAvzi9K7DQnbgooV5tF_f1nwWgh7LwXcny4BJRXxCF_bLT1aNmS_-qGaob1q8ahCJC_7g6R6rRP/s1600/Logo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;img border="0" data-original-height="175" data-original-width="287" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiilek6nVNMeYsb7Q66aqf9CPo2HGdKAPnHRgACp5l2Pt7NWTZMDco2dVubwHAvzi9K7DQnbgooV5tF_f1nwWgh7LwXcny4BJRXxCF_bLT1aNmS_-qGaob1q8ahCJC_7g6R6rRP/s1600/Logo.png" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit;"&gt;Construcción de métodos JavaScript&lt;/span&gt;&lt;/h4&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;Con éste fin Omnis dispone de un nuevo archivo JS, denominado "ow3javascript.js", el cual podremos localizar bajo el directorio "clientserver/server/remotedebug" y que es el punto de partida para todas las llamadas a los métodos de "node.js". Éstas llegaran desde Omnis como solicitudes HTTP y retornaran sus resultados también como contenido HTTP. Cada "Worker" ejecutará sus métodos secuencialmente.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;Un nuevo directorio o carpeta denominada "node_modules", contendrá los módulos que serán requeridos desde el "ow3javascript.js". Es aquí, donde deberemos ubicar lo módulos "node.js" que deseemos utilizar, mediante el comando "npm -i" ejecutado desde ésta misma carpeta; éstos serán los módulos que ineraccionaran con nuestras aplicaciones Omnis.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;Existen al menos dos archivos clave que siempre deberán estar ubicados y presentes en ésta carpeta:&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="font-size: 11pt;"&gt;omnis_calls.js - M&lt;/span&gt;&lt;span style="text-align: start;"&gt;ódulo que encargado de devolver los resultados a Omnis.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="font-size: 11pt;"&gt;omnis_modules.js - M&lt;/span&gt;ódulo encargado de suministrar la lista de los que podrán ser invocados desde Omnis.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: inherit;"&gt;En ésta misma carpeta, podremos localizar dos módulos suministrados a modo de ejemplo denominados: "omnis_test.js" y "omnis_xml2js.js". Vistos desde Omnis sus nombres son "test" y "xml2js", a cada uno de ellos le corresponderá una entrada en el "omnis_modules.js" proporcionándose así la lista de métodos que podrán ser invocados desde Omnis.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit;"&gt;Creación de un "Worker"&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;Asigne el subtipo del objeto externo "OW3 Worker Objects\JAVASCRIPTWorker", a una variable de tipo "&lt;span style="font-size: 11pt;"&gt;Object&lt;/span&gt;" u "&lt;span style="font-size: 11pt;"&gt;Object Reference&lt;/span&gt;", , también puede hacerse mediante crear una clase objeto a la que asignar el "subtipo" ya indicado, para luego asignarlo a una variable Omnis.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: inherit;"&gt;¡¡Importante!! Antes de invocar su método "$init", será necesario configurar su propiedad&amp;nbsp;&lt;/span&gt;"$callbackinst",&amp;nbsp;para indicar dónde recibir los resultados. Por ejemplo: "Calculate Object.$callbackinst as $cinst"&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit;"&gt;Propiedades&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;El "Worker JavaScript" soporta las propiedades "Worker" estándar: $state, $threadcount, $errorcode y $errortext.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit;"&gt;Métodos de invocación&lt;/span&gt;&lt;/h4&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit; font-size: 11pt;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit; font-size: 11pt;"&gt;$init([cPath, bDebugNodeJs=kFalse])&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;Permite preparar el objeto, de forma que esté listo para ejecutar llamadas a métodos JavaScript. Devuelve "true" si tiene éxito. Debe ejecutarse antes que cualquier otro método.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;div class="page" style="text-align: start;" title="Page 79"&gt;
&lt;div class="layoutArea"&gt;
&lt;div class="column"&gt;
&lt;span style="font-weight: 700;"&gt;&lt;span style="font-family: inherit;"&gt;cPath&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;Permite cambiar la ruta de búsqueda de módulos predeterminada "NODE_PATH". La ruta predeterminada es "≤Carpeta de datos Omnis≥/node_modules". Tenga en cuenta, que&amp;nbsp;sí&amp;nbsp;cambia esta ruta, el resto de módulos que son obligatorios también deberán ser alojados en la nueva ruta.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;div style="text-align: start;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;span style="font-family: inherit; font-weight: 700;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="page" style="text-align: start;" title="Page 79"&gt;
&lt;div class="layoutArea"&gt;
&lt;div class="column"&gt;
&lt;span style="font-weight: 700;"&gt;&lt;span style="font-family: inherit;"&gt;bDebugNodeJs&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;span style="font-family: inherit;"&gt;Booleano que indica si se desea poder depurar "node.js", por ejemplo, mediante Chrome. Es posible que no pueda iniciarse el "Worker" si se configura para más de un "Worker JavaScript" en activo, ya que "node.js" requiere de un puerto para depuración disponible. Para su depuración en Chrome,&amp;nbsp;introduzca&amp;nbsp;"chrome://inspect", y luego abra las herramientas de depuración dedicadas para "node.js".&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit;"&gt;$start()&lt;/span&gt;&lt;/h4&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;Ejecuta el&amp;nbsp;&lt;span style="text-align: justify;"&gt;"Worker JavaScript"&lt;/span&gt;&amp;nbsp;en segundo plano. Devuelve "true" sí ha sido iniciado correctamente.&amp;nbsp;El método $start(), se encargará de iniciar "node.js" he invocar los métodos JavaScript. Seguramente realizaremos llamadas a diferentes métodos del mismo proceso, por lo que no será necesario ejecutar $start() con frecuencia, lo que significa que la sobrecarga debida a la ejecución de procesos "node.js" es mínima.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit;"&gt;$cancel&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;Cancela la ejecución del proceso "node.js". Cualquier método ya en progreso no será completado.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit;"&gt;$callmethod(cModule, cMethod, vListOrRow [,bWait=kFalse, &amp;amp;cErrorText])&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div style="font-family: inherit; text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;Permite la invocación de un método, al cual se pasa un solo parámetro desde el objeto JavaScript ("vListOrRow"). Opcionalmente se esperará a que el método complete su ejecución ("bWait"). El método devolverá "true" si la invocación es exitosa.&amp;nbsp;&lt;span style="font-family: inherit;"&gt;"cModule" y "cMethod" identifican al módulo y al método dentro del módulo, que será invocado.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;"vListOrRow" será convertido a formato JSON antes de su paso al método como parámetro.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;El uso de&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;"bWait" indicará que deseamos suspender la ejecución, hasta que&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;el método haya terminado&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;. "&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;cErrorText" recibirá un texto descriptivo del error, en caso de fallo de "$callmethod".&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="font-family: inherit;"&gt;
&lt;/span&gt;
&lt;br /&gt;
&lt;div style="font-family: inherit; text-align: justify;"&gt;
&lt;span style="font-family: inherit;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="font-family: inherit;"&gt;
&lt;/span&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit;"&gt;
&lt;span style="font-family: inherit;"&gt;Métodos de retorno&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;span style="font-family: inherit;"&gt;
&lt;/span&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="font-family: inherit;"&gt;
&lt;/span&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span style="font-family: inherit;"&gt;
$cancelled&lt;/span&gt;&lt;/h4&gt;
&lt;span style="font-family: inherit;"&gt;
&lt;/span&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="font-family: inherit;"&gt;
&lt;div&gt;
Se puede reescribir este método (Override) si se desea controlar la notificación correspondiente a una cancelación del "Worker" realizada correctamente.&lt;/div&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h4&gt;
$workererror(wError)&lt;/h4&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La reescritura de éste método (Override), permite recibir notificaciones de error del "Worker" no relacionados con la invocación a alguno de sus métodos, como, por ejemplo, un error producido al iniciarse "node.js". El sub-proceso del "Worker" se cerrará tras la generación de dicha notificación. "wError" contiene dos columnas, un entero llamado "errorCode" y un texto llamado "errorInfo".&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
$methoderror(wError)&lt;/h4&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
La re-escritura de éste método (Override), permite recibir notificaciones de error tras el intento de invocar un método mediante "$callmethod". "wError" tiene dos columnas, un entero llamado "errorCode" y un texto llamada "errorInfo".&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
$methodreturn(wReturn)&lt;/h4&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div style="text-align: justify;"&gt;
Éste es el método al cual llegarán los resultados tras la ejecución de un "$callmethod". "wReturn" es una variable de tipo "row". Si el método de JavaScript devuelve un objeto, será el equivalente Omnis creado al convertir el JSON en una "row". Si el método de JavaScript devuelve otros datos, como por ejemplo. una imagen, esta consistirá en una "row" con una sola columna denominada "content", con los datos devueltos por el método.&lt;/div&gt;
&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiilek6nVNMeYsb7Q66aqf9CPo2HGdKAPnHRgACp5l2Pt7NWTZMDco2dVubwHAvzi9K7DQnbgooV5tF_f1nwWgh7LwXcny4BJRXxCF_bLT1aNmS_-qGaob1q8ahCJC_7g6R6rRP/s72-c/Logo.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>El nuevo Depurador Remoto </title><link>http://framosmu.blogspot.com/2019/02/el-nuevo-depurador-remoto.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Wed, 26 Dec 2018 08:28:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-1401781463723018879</guid><description>&lt;div style="text-align: justify;"&gt;
La depuración remota permite depurar el código Omnis de una librería compartida en la red. Omnis usa para ello una versión “developer” independiente, el llamado “remote debug client”, el cual se conectará a través de la red a otro Omnis Studio, denominado “remote debug server”.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKZMwdEYe0uQ9TdQlgvqDTGT4vcl4yHo9XCBIMnVtAmq3XzZu6XfzsWNGkIuXSHntOPJpl3b0vpMRDLET4T5Fg0wqM1PYv6NfJ7uPMEheTMz9rMjKHJ1_LohglpBTSHV1bxsZz/s1600/Imagen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="597" data-original-width="1043" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKZMwdEYe0uQ9TdQlgvqDTGT4vcl4yHo9XCBIMnVtAmq3XzZu6XfzsWNGkIuXSHntOPJpl3b0vpMRDLET4T5Fg0wqM1PYv6NfJ7uPMEheTMz9rMjKHJ1_LohglpBTSHV1bxsZz/s400/Imagen.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Algunos aspectos a tener en cuenta:&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;El “remote debug server” es quien ejecuta el código a depurar, y puede residir en cualquier tipo de instalación: “development”, “runtime”, “server” o “headless server”.&lt;/li&gt;
&lt;li&gt;El código Omnis es ejecutado en modo “multi-threaded server”, creándose para ello pilas de procesos independientes de la principal.&lt;/li&gt;
&lt;li&gt;El “remote debug server” y el “client” no precisan estar ejecutándose en el mismo sistema operativo.&lt;/li&gt;
&lt;li&gt;La versión “client” debe ser la misma o posterior a la versión “server”.&lt;/li&gt;
&lt;li&gt;Las clases protegidas y las bibliotecas bloqueadas también pueden ser depuradas.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;
Aunque hablamos de “depurador remoto”, en realidad, tanto el cliente como el servidor podrían residir en la misma máquina, de hecho cliente y servidor podrían contener los mismos procesos Omnis. En este último caso, el “remote debug client” es ejecutado con algunas restricciones, indicadas mas adelante en este artículo.&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Conectividad&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;div&gt;
El “client” y el “server” se conectan entre sí a través de un WebSocket. Una conexión &lt;b&gt;WebSocket&lt;/b&gt; es una conexión directa entre cliente y servidor, por lo que puede requerir de la apertura del puerto correspondiente en el “firewall”. Puesto que las conexiones WebSocket se inician como conexiones HTTP, un WebSocket puede soportar una conexión TLS segura, así como el requerimiento de un certificado de autenticación para el cliente. El “remote debug”, usa siempre una conexión TLS, por lo que el WebSocket es iniciado como HTTPS.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
La conexión entre un cliente y un servidor es denominada “remote debug session” o simplemente “session”. Omnis podrá ejecutar una sola “session” a la vez.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
El "Remote Debug Server"&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Desde la versión “developer”, podremos configurar el “remote debug server” tras hacer clic sobre su nodo en el “Browser”, y seleccionar la opción “Remote Debug Server”.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Para una versión “runtime” de Omnis (no “headless”), y si la librería “remotedebug.lbs” está en la carpeta “startup”, se dispondrá de un menú denominado “Remote Debug”. El cual contiene una sola opción, que permite abrir la ventana de configuración. Si se trata de un servidor “headless” podremos llevar a cabo la configuración desde la ventana de administració (osadmin).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
La ventana de configuración muestra dos pestañas, una para controlar el servidor y otra para configurarlo.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
La pestaña “Control Server” tiene un solo botón, utilizado para arrancar o detener el servidor. De no encontrarse arrancado, no aceptará conexiones desde un cliente.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
La pestaña “Configure Server” permite llevar a cabo su configuración, muestra los campos que corresponden a las entradas en el archivo de configuración y que describiremos a continuación.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
El fichero de configuración&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
La configuración se guarda en el fichero denominado &amp;nbsp;“remote_debug_server_config.json”, ubicado en “clientserver/server/remotedebug” de la carpeta de instalación Omnis. Podemos optar por editar este archivo JSON directamente con cualquier editor o usar la opción descrita anteriormente.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Debemos tener en cuenta que Omnis hace uso de un servidor “&lt;b&gt;node.js&lt;/b&gt;” ejecutado junto con Omnis, desde el se construye el servidor WebSocket. Como consecuencia, parte de la información de configuración es compartida también con “node.js”.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Configuración ejemplo:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
{&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; &amp;nbsp;"debugPort": 8080,&amp;nbsp;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; "serverPfx": "server.pfx",&amp;nbsp;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; "pfxPassPhrase": "xxxxxx",&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; &amp;nbsp;"ca": [ "server_cert.pem" ],&amp;nbsp;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; "requestCert": false,&amp;nbsp;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; "rejectUnauthorized": &amp;nbsp;false,&amp;nbsp;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; "userName": "myUser",&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp;"hashedPassword": &amp;nbsp;&amp;nbsp;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp;"AAGGoAAAABBSEkknQUIeHQHu1sIyWxlSAAAAIHw9kvCVF4tE//S &amp;nbsp; MpbSGVD/RKJLekoR7TlTvZVy3MbkJ",&amp;nbsp;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; &amp;nbsp;"startRemoteDebugServerAtStartup": true,&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; &amp;nbsp;"pauseAtStartupUntilDebuggerClientStartsExecution": false,&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&amp;nbsp; &amp;nbsp;"logConnectionSetup": false&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
}&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
debugPort&lt;/h4&gt;
&lt;div&gt;
El puerto TCP/IP en el que el servidor WebSocket escucha las conexiones entrantes desde el cliente.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
serverPfx&lt;/h4&gt;
&lt;div&gt;
Este es un archivo que contiene el certificado del servidor y la clave privada. Debe estar en el mismo directorio que el “remote_debug_server_config.json”. La instalación por defecto consta de un certificado auto-firmado y una clave generada mediante el comando openssl (disponible en cualquier sistema con openssl instalado). Tendrá que proporcionar su propia clave privada y su certificado. Puede generar una nueva clave privada y un certificado auto-firmado utilizando los siguientes comandos:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
openssl req -x509 -newkey rsa:4096 -keyout server_key.pem -out server_cert.pem -nodes -days 1024 -subj "/CN=localhost/O=Demo" -passin pass:xxxxxx&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
openssl pkcs12 -export -out server.pfx -inkey server_key.pem -in server_cert.pem&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;br /&gt;
Este archivo deberá ser indicado bajo la opción “PFX” y es invocado por el método https.createServer() de “node.js”. Podrá encontrar más información sobre esto, en la documentación de “node.js”:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
https://nodejs.org/docs/latest-v8.x/api/https.html#https_class_https_serve&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
https://nodejs.org/docs/latest-v8.x/api/tls.html#tls_tls_createsecurecontext_options&lt;/blockquote&gt;
&lt;br /&gt;
&lt;h4&gt;
pfxPassPhrase&lt;/h4&gt;
&lt;div&gt;
Esta es la frase-contraseña utilizada para proteger el archivo PFX en el servidor. En nuestro ejemplo es "xxxxxx".&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
ca&lt;/h4&gt;
&lt;div&gt;
Ver https://nodejs.org/docs/latest-v8.x/api/tls.html#tls_tls_createsecurecontext_options para más detalles. Normalmente, usted sólo tendrá un CA, puesto que tiene un sólo certificado auto-firmado, en cuyo caso tendremos una sola entrada. En nuestro ejemplo el certificado fue firmado usando “server_cert.pem”. Generalmente su valor es una lista separada por comas de certificados de confianza, nombres de archivos los cuales deben residir en el mismo directorio que el “remote_debug_server_config.json”.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
requestCert&lt;/h4&gt;
&lt;div&gt;
Valor booleano. Si es verdadero, el servidor “node.js” solicitará un certificado para autenticar al cliente. Los certificados de cliente se explican más adelante, en la entrada conectividad del cliente.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
rejectUnauthorized&lt;/h4&gt;
&lt;div&gt;
Valor booleano. Si es verdadero, el servidor rechazará cualquier conexión no incluida en la lista de CA’s suministrada. Esta opción solo tiene efecto si “requestCert” es cierto.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
userName&lt;/h4&gt;
&lt;div&gt;
Si no está vacío, la conexión WebSocket también usará autenticación básica HTTP con el usuario, en cuyo caso este campo deberá contener el nombre del usuario utilizado para la autenticación básica HTTP.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
hashedPassword&lt;/h4&gt;
&lt;div&gt;
Si “userName” no está vacío, será el "hash" PBKDF2 de la contraseña requerida para la autenticación básica HTTP.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
startRemoteDebugServerAtStartup&lt;/h4&gt;
&lt;div&gt;
Esta opción booleana indica si el “remote debug server” debe iniciarse &amp;nbsp;automáticamente al iniciarse Omnis.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
pauseAtStartupUntilDebuggerClientStartsExecution&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
Si el “remote debug server” está configurado para iniciarse automáticamente cuando se inicia Omnis, podremos configurar esta opción booleana a “true” para causar que Omnis pause su ejecución durante el momento de ejecutar la “startup_task” y otras "tasa" iniciales de nuestra librería Omnis.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Cuando se utiliza esta opción, Omnis muestra un mensaje de trabajo (Waiting for remote debug client to start execution…), entrando en un bucle de espera, hasta que se reciba un comando desde el cliente para ejecución. Durante este bucle, el cliente podrá ver y depurar el código remotamente, mediante (por ejemplo) establecer puntos de interrupción.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
El bucle termina cuando el cliente envía un comando de inicio de ejecución, cuando la sesión con el “remote debug server” es cerrada o cuando un usuario hace clic sobre el botón “cancel” situado junto al mensaje de trabajo mostrado en el servidor. Cuando el bucle termina, Omnis ejecutará la “startup_task” de la librería.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
El “Remote Debug Client”&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
El “remote debug client” es accesible a través de un nuevo nodo situado sobre el árbol del navegador de Studio denominado, "Remote Debug Client". Utiliza un modelo de sesión similar al de VCS. Tras hacer clic sobre el nodo, se mostrarán los enlaces “Session Manager”, y “Open Session”.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
El “Session Manager” permite configurar las sesiones de depuración remotas. Cada sesión contendrá los parámetros que permitirá al cliente iniciar un WebSocket de conexión con un “remote debug server”. A continuación describimos cada uno de sus parámetros:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Name&lt;/h4&gt;
&lt;div&gt;
Nombre que identifica el sesión.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Server&lt;/h4&gt;
&lt;div&gt;
Dirección IP o nombre DNS del “remote debug server”.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Debug Port&lt;/h4&gt;
&lt;div&gt;
Puerto configurado en el “remote debug server”. En su conexión al servidor, el cliente construirá la URL siguiente:&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;div class="MsoNormal" style="font-family: Calibri, sans-serif; font-size: 11pt; margin: 3pt 6.85pt 0.0001pt 101.9pt;"&gt;
&lt;u&gt;&lt;span lang="EN-US" style="color: #000099; font-family: &amp;quot;courier new&amp;quot;;"&gt;wss://Server:DebugPort&lt;/span&gt;&lt;/u&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
Client Certificate&lt;/h4&gt;
Si el servidor requiere un certificado de cliente, deberá especificarse aquí. Podrá generar un certificado de cliente usando los siguientes comandos openssl:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
openssl req -newkey rsa:4096 -keyout client_key.pem -out client_csr.pem -nodes -days 1024&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;-subj "/CN=192.168.1.11" -passin pass:xxxxxx&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
openssl x509 -req -in client_csr.pem -CA server_cert.pem -CAkey server_key.pem -out client_cert.pem -set_serial 01 -days 1024&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
Tenga en cuenta que en este ejemplo usamos la clave y el certificado de servidor utilizados con el ejemplo para el “PFX”. Paro, el certificado del cliente necesitará ser instalado en la máquina del cliente.&lt;br /&gt;
&lt;br /&gt;
Para Windows, genere un archivo “client.pfx”:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
openssl pkcs12 -export -out client.pfx -inkey client_key.pem -in client_cert.pem&lt;/blockquote&gt;
Añada el “client.pfx” al almacén de certificados de Windows, mediante hacer doble clic &amp;nbsp;en el archivo, agregándolo a “Personal certificates” del usuario en curso.&lt;br /&gt;
&lt;br /&gt;
Para macOS, genere un archivo “pkcs12”:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
openssl pkcs12 -export -out client.p12 -inkey client_key.pem -in client_cert.pem&lt;/blockquote&gt;
Haga doble clic sobre el archivo para agregarlo al llavero.&lt;br /&gt;
Puede encontrar más detalles sobre esto en la documentación sobre CURL en:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
https://curl.haxx.se/libcurl/c/CURLOPT_SSLCERT.html&lt;/blockquote&gt;
Tenga en cuenta que el parámetro “Client Certificate” pasa su valor al comando CURL bajo la opción CURLOPT_SSLCERT.&lt;br /&gt;
&lt;br /&gt;
En caso de Windows, el parámetro es la ruta hacia el lugar donde está almacenado…&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
CurrentUser\MY\afe2179599460d20da08c12e8c328d84bd300735&lt;/blockquote&gt;
…donde afe2179599460d20da08c12e8c328d84bd300735 es la huella digital, visible mediante hacer doble clic en “certificate” del MMC (MMC certificate snap-in view, pestaña “details”, campo “thumbprint”).&lt;br /&gt;
&lt;br /&gt;
En caso de macOS, se puede especificar la ruta del archivo “p12” o el nombre que tiene en el llavero del cliente.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
User Name&lt;/h4&gt;
&lt;div&gt;
Si el servidor utiliza autenticación básica HTTP, es el nombre de usuario requerido.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Password&lt;/h4&gt;
&lt;div&gt;
Si el servidor usa autenticación básica HTTP, será la contraseña requerida. &amp;nbsp;Alternativamente, podrá dejarse vacía, causando que se le solicite al cliente la cuando sea necesaria.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Server Connection Logging&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
Mediante ésta opción podremos monitorizar la conexión con el “remote debug server”, para poder observar cualquier problema de conexión. También deberemos habilitar ésta opción en el archivo de configuración, bajo la entrada “logConnectionSetup”.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Si está habilitado, se creará un archivo de registro &amp;nbsp;denominado: “&lt;nombre de="" n="" sesi=""&gt;.htm” en el directorio “logs/remotedebug , con el registro de lo que ha ocurrido al conectarse al “remote debug server”. Tenga en cuenta que el registro no se escribe hasta que la conexión es cerrada.&lt;/nombre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Preparación del código para su depuración remota&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Deberemos habilitar en nuestras librerías e instancias de tipo tarea “task” la capacidad “remote debugging” mediante configurar su propiedad $remotedebug.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Library&lt;/h4&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Por defecto, una librería no puede ser depurada remotamente, lo que significa que cuando el cliente intente conectarse para depuración, normalmente no aparecerá en el interfaz de cliente. Si queremos que aparezca necesitaremos establecer su propiedad “$clib.$remotedebug”, como “True”, lo cual no podrá realizarse sobre librerías ya marcadas como privadas, lo que significa que deberemos fijar esta propiedad como “true” antes de hacerla privada.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Task&lt;/h4&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
La configuración de “$clib.$remotedebug” permite que la librería y sus clases aparezcan sobre la ventana cliente de depuración remota. Permitiéndonos manipular su código y establecer “break points”.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Sin embargo, sólo las clases “task” y “remote task” marcadas para depuración remota, reaccionarán ante los “breack points” que fijemos. Esto permitirá un mayor control sobre lo que podrá o no podrá ser depurado remotamente y del lado del servidor, permitirá evitar que un “breack point” detenga la ejecución para otros posibles clientes en uso.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Para marcar una “task” o “remote task” para depuración remota, configure su propiedad&lt;/div&gt;
&lt;div&gt;
“$remotedebug” a kTrue.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Tabién podremos activar ésta propiedad, cómo un parámetro en el URL de conexión, hacia un “remote form” (omnisRemoteDebug = 1), por ejemplo:&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
http://127.0.0.1:5981/jschtml/jsDragDrop.htm?omnisRemoteDebug=1&lt;/blockquote&gt;
&lt;br /&gt;
&lt;h3&gt;
Interfaz del depurador remoto&amp;nbsp;&lt;/h3&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h4&gt;
Abriendo un sesión&lt;/h4&gt;
&lt;h4&gt;
&lt;/h4&gt;
Para usar el “remote debugger client” tras configurar una sesión, haga clic sobre el nodo “Remote Debug Client” y después sobre el enlace “Open Session”, luego haga clic sobre el enlace correspondiente a la sesión que deseemos utilizar.&lt;br /&gt;
&lt;br /&gt;
Esto hará que el cliente inicie una conexión WebSocket con el servidor. Mientras se establece, se mostrará su progreso sobre el panel del navegador, aunque suele ser muy rápido. Además, aparecerá un nuevo enlace durante éste proceso denominado “Cancel Open Session”.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Browsing Libraries&lt;/h4&gt;
&lt;h4&gt;
&lt;/h4&gt;
Una vez abierta la sesión, se mostrarán las bibliotecas marcadas para depuración remota.&lt;br /&gt;
&lt;br /&gt;
Los nodos secundarios del “Remote Debug Client” tienen un comportamiento similar al de los habituales para la edición de librerías. Cuando seleccionamos alguno de éstos nodos secundarios, el panel del navegador se actualizará para mostrar su contenido permitiendo la edición de todo el contenido de la librería.&lt;br /&gt;
&lt;br /&gt;
Si se selecciona una sola clase en el panel del navegador, se mostrará un enlace denominado "Open debug window". Haga clic sobre él para abrir la ventana de depuración remota para esa clase.&lt;br /&gt;
&lt;br /&gt;
Finalmente, si el servidor está en pausa y por tanto a la espera de ejecutar el inicio, entre los enlaces podrá ver uno con el nombre “Run Startup”, mediante el cual podrá indicar al servidor que debe continuar y ejecutar su proceso inicial.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
La ventana del “Remote Debug”&lt;/h4&gt;
&lt;h4&gt;
&lt;/h4&gt;
Esta ventana muestran un diseño muy similar al del editor de métodos. Su diferencia principal está en que siempre muestra el panel de depuración y no existe un panel de edición, y en su esquina inferior derecha aparece un nuevo panel de variables.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
La barra de herramientas (Instance)&lt;/h4&gt;
&lt;h4&gt;
&lt;/h4&gt;
Permite mostrar los métodos u objetos específicos de una instancia actualmente en uso. El menú “Instance” nos permitirá cerrarla, así como también retirarla o añadirla a la lista del depurador.&lt;br /&gt;
&lt;br /&gt;
Tenga en cuenta que este menú se desactiva tan pronto como la ventana de depuración remota es asociada, es decir durante el proceso de depuración de una instancia.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Observaciones&lt;/h4&gt;
&lt;h4&gt;
&lt;/h4&gt;
Deberemos tener presente que el conjunto de librerías e instancias, susceptibles de ser depuradas pueden cambiar en el servidor. Omnis mantiene al cliente constantemente actualizado con respecto a la situación en que se encuentre el servidor. Por ejemplo, si una librería se cierra en el servidor, se informa al cliente y se actualiza su interfaz lo que significa su eliminación del navegador y el cierre de cualquier ventana de depuración remota relacionada. Sin embargo, si se producen cambios en un método en el servidor, el cliente no recibirá el método actualizado hasta que sea de nuevo solicitado, debe tenerse en cuenta que cada vez que el cliente realiza una operación de depuración, el cliente solicita el método y retiene una copia del mismo, hasta que la acción termina, si durante ese proceso, el método ha cambiado en el servidor, el cliente no lo recibirá hasta necesitar una nueva copia.&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKZMwdEYe0uQ9TdQlgvqDTGT4vcl4yHo9XCBIMnVtAmq3XzZu6XfzsWNGkIuXSHntOPJpl3b0vpMRDLET4T5Fg0wqM1PYv6NfJ7uPMEheTMz9rMjKHJ1_LohglpBTSHV1bxsZz/s72-c/Imagen.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>Omnis Developers Conference, Mexico City – Lunes 11 de Marzo 2019</title><link>http://framosmu.blogspot.com/2019/01/omnis-developers-conference-mexico-city.html</link><category>#AULAOMNIS</category><category>#OMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Tue, 25 Dec 2018 13:00:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-4359245996471560956</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://www.softpi.com/es/omnis-developers-conference-mexico-city-lunes-11-de-marzo-2019/"&gt;&lt;img border="0" data-original-height="990" data-original-width="1600" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhQ_PJzwy2MdUAMqP7bhkrn8x1fix9icUmybf9TDEdtWraxnpNguvVX3pqLXxMYR9EUP9MdQ2nvapicPhhHcb0IHkwvHh94ZcdKJVR5umD1kSZkWf0_3-4GI8ahINuSxOm7e67/s640/OM_DC2019_Mexico19-2-1136x702%25402x.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="fusion-text" style="box-sizing: border-box; caret-color: rgb(51, 51, 51); color: #333333; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; font-size: 15px;"&gt;
&lt;div style="box-sizing: border-box; margin-bottom: 20px;"&gt;
&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;b style="box-sizing: border-box;"&gt;&lt;i style="box-sizing: border-box;"&gt;Lunes 11 de Marzo 2019,&amp;nbsp; Omnis Developers Conference, Mexico City&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;b style="box-sizing: border-box;"&gt;&lt;i style="box-sizing: border-box;"&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
&lt;b style="box-sizing: border-box;"&gt;&lt;i style="box-sizing: border-box;"&gt;&lt;b style="box-sizing: border-box;"&gt;&lt;i style="box-sizing: border-box;"&gt;&lt;span style="box-sizing: border-box;"&gt;Martes 12 + Miercoles 13 Marzo 2019&lt;/span&gt;,&amp;nbsp; Omnis Academy, Mexico City&lt;/i&gt;&lt;/b&gt;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;b style="box-sizing: border-box;"&gt;&lt;i style="box-sizing: border-box;"&gt;
&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div class="fusion-text" style="box-sizing: border-box; caret-color: rgb(51, 51, 51); color: #333333; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; font-size: 15px;"&gt;
&lt;div style="box-sizing: border-box; margin-bottom: 20px;"&gt;
&lt;b style="box-sizing: border-box;"&gt;&lt;i style="box-sizing: border-box;"&gt;Objetivos&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;ul style="box-sizing: border-box;"&gt;
&lt;li style="box-sizing: border-box;"&gt;Conocer OMNIS Studio&lt;/li&gt;
&lt;li style="box-sizing: border-box;"&gt;Presentar de la nueva versión 10&lt;/li&gt;
&lt;li style="box-sizing: border-box;"&gt;Componer aplicaciones que traspasan las fronteras&lt;/li&gt;
&lt;li style="box-sizing: border-box;"&gt;Componer aplicaciones Web y Moviles (Android, iOS, Windows 10)&lt;/li&gt;
&lt;li style="box-sizing: border-box;"&gt;Establecer contactos, conociendo más detalle sobre aplicaciones y proyectos.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="fusion-text" style="box-sizing: border-box; caret-color: rgb(51, 51, 51); color: #333333; font-family: &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; font-size: 15px; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;span style="font-size: 18.66666603088379px; font-weight: 700; text-align: center;"&gt;&lt;a href="https://www.softpi.com/es/omnis-developers-conference-mexico-city-lunes-11-de-marzo-2019/"&gt;Consulte la agenda e inscríbase hoy mismo...&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhQ_PJzwy2MdUAMqP7bhkrn8x1fix9icUmybf9TDEdtWraxnpNguvVX3pqLXxMYR9EUP9MdQ2nvapicPhhHcb0IHkwvHh94ZcdKJVR5umD1kSZkWf0_3-4GI8ahINuSxOm7e67/s72-c/OM_DC2019_Mexico19-2-1136x702%25402x.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item><item><title>¡El anuncio anticipado de un punto de viraje en la ya larga historia de Omnis!</title><link>http://framosmu.blogspot.com/2018/11/el-anuncio-anticipado-de-un-punto-de.html</link><category>#AULAOMNIS</category><author>noreply@blogger.com (Aula Omnis Studio)</author><pubDate>Fri, 2 Nov 2018 08:50:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-31245983.post-7161793997578718074</guid><description>Esta entrada en el blog, no es para describiros una característica de Omnis Studio, ni para (como os tengo acostumbrados) arrojar nueva luz sobre como hacer las cosas con ésta magnífica herramienta, simplemente es que no me he podido resistir a perder la ocasión de hacerme eco del más que interesante anuncio que Omnis a hecho el pasado 1 de Noviembre del 2018.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Sin duda y como reza en el título de ésta entrada, marcará una "antes-y-después" en la historia de Omnis Studio. Será muy emocionante ir descubriendo las novedades que nos esperan.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;a href="https://developer.omnis.net/blog/an-important-announcement-about-omnis-studio"&gt;&lt;span style="font-size: large;"&gt;Omnis Studio 10&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;img border="0" data-original-height="645" data-original-width="1038" height="395" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLnaSk8J6Qajzmse5roWzSSwy9GAXJ-qljha0wcszzTpt0mB7HS2ktvQk0XODC8e5Tz3UA5dqwvLGWmogxqf1ncYENWsg6H0QQ7k6B4hnuqoYSEUUTDcadVegcaO2RE85qSBH7/s640/Omnis_Studio10_Blog01-1038x645.png" width="640" /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLnaSk8J6Qajzmse5roWzSSwy9GAXJ-qljha0wcszzTpt0mB7HS2ktvQk0XODC8e5Tz3UA5dqwvLGWmogxqf1ncYENWsg6H0QQ7k6B4hnuqoYSEUUTDcadVegcaO2RE85qSBH7/s72-c/Omnis_Studio10_Blog01-1038x645.png" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></item></channel></rss>