Silverlight 3 Beta 1:  Aplicaciones Fuera del Navegador

Nota 21/Junio/2010: Este artículo fue hecho con SL3 Beta 1 pero en la versión 4 ocurrieron muchos cambios con respecto a a las Aplicaciones Fuera del Navegador.  Te recomiendo que mejor vean este screencast para tener la información más actualizada:

http://channel9.msdn.com/posts/Channel9Mexico/15-Aplicaciones-Fuera-del-Navegador/

Introducción

Una de las características nuevas incluidas en la última versión de Silverlight: Silverlight 3 Beta 1 es el soporte a que nuestras aplicaciones puedan ejecturse fuera del navegador (OOB por sus siglas en inglés Out Of Browser), esto es, que no tengas que navegar a página equis de sitio ye para poder correr dicha aplicación.  Más que un simple código que debemos agregar a nuestra aplicación, esta característica tiene muchos detalles que vale la pena explicar paso a paso.  El objetivo de este artículo es precisamente eso.

Elemento Deployment.ApplicationIdentity

Para que nuestra aplicación pueda ser ejecutada fuera del navegador necesitamos habilitar esta opción modificando el manifiesto (implementado en el archivo AssemblyManifest.xml) de nuestro proyecto de Silverlight 3 agregando el elemento ApplicationIdentity.  Con este elemento podemos establecer diversas propiedades para nuestra aplicación como el nombre, el título de la ventana, la descripción y los iconos a mostrar cuando esté la aplicación como acceso directo en el escritorio, en la barra de tareas, etc.

Cabe mencionar que las plantillas de Silverlight 3 Beta 1 para Visual Studio .NET 2008 ya incluyen el elemento ApplicationIdentity encerrado en un bloque de comentario, para simplemente “descomentarlo” y habilitar la opción de una manera sencilla.  Por el otro lado, si estás convirtiendo un proyecto de Silverlight 2 a Silverlight 3 Beta 1 –como es el caso de este artículo-, el Asistente de Conversión NO agregará de manera automática el elemento ApplicationIdentity y lo tendrás que agregar manualmente.  A esto debemos añadir que no hay actualmente soporte de Intellisense para este elemento cuando lo estamos editando en Visual Studio.

Ahora para que este artículo esté basado en una aplicación real voy a utilizar el ejemplo del Silverlight Fred (sencillo juego de memoria que asemeja al Fabuloso Fred: famoso juguete en la década de los 80) publicado hace algunos días y le agregaremos la característica de ejecutar Fuera del Navegador.

Iconos

El elemento Deployment.ApplicationIdentity soporta el subelemento ApplicationIdentity.Icons en el cual podemos establecer los iconos que nuestras aplicación requiera.  Podemos establecer cuatro tamaños para los iconos:

  • 128×128
  • 48×48
  • 32×16
  • 16×16

El tamaño de 128×128 es utilizado por la caja de diálogo cuando estemos “instalando” la aplicación Fuera del Navegador, el resto son utilizados por el Sistema Operativo para el acceso directo del escritorio (en Windows), el icono para la ventana de la aplicación, el taskbar, etc.)

El siguiente código muestra el manifiesto completo del proyecto de Silverlight 3 con el elemento ApplicationIdentity incluido:

<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
    <Deployment.Parts>
    </Deployment.Parts>

    <Deployment.ApplicationIdentity>
        <ApplicationIdentity ShortName="Silverlight Fred"
                             Title="Silverlight Fred Fuera del Navegador">
            <ApplicationIdentity.Blurb>
                Este es un sencillo juego de memoria que se asemeja al Fabuloso Fred, famoso juego en la década de los 80's
            </ApplicationIdentity.Blurb>
            <ApplicationIdentity.Icons>
                <Icon Size="16x16">Icons/Icon16.png</Icon>
                <Icon Size="32x32">Icons/Icon32.png</Icon>
                <Icon Size="48x48">Icons/Icon48.png</Icon>
                <Icon Size="128x128">Icons/Icon128.png</Icon>
            </ApplicationIdentity.Icons>
        </ApplicationIdentity>
    </Deployment.ApplicationIdentity>
</Deployment>

En este caso estoy usando cuatro iconos, uno para cada tamaño en formato en PNG.  Es importante comentar que los iconos deberán estar marcados como “Content” en Visual Studio para que sean parte del .XAP y no como recursos adjuntos del ensamblado principal:

Instalación

Podemos instalar las aplicaciones Silverlight 3 Fuera del Navegador de dos maneras:

  1. Programáticamente, en respuesta a un evento lanzado por el usuario (el clic de un botón, el presionar una tecla, etc.) utilizando el método Application.Current.Detach()
  2. Haciendo clic secundario en la aplicación en el Navegador y seleccionar la opción de “Instalar <nombre de aplicación> en este equipo”

La siguiente figura muestra la opción en el menú contextual al hacer clic-secundario sobre la aplicación en el Navegador:

Ahora bien, sea cual fuese el mecanismo por el cual se instala la aplicación de Silverlight 3 Fuera del Navegador, se mostrará la siguiente caja de diálogo:

Es en esta caja de diálogo en donde determinamos si queremos un acceso directo en nuestro escritorio o en el grupo de programas, además podemos observar cómo es mostrado el icono de tamaño 128×128 anteriormente descrito en este artículo.

Una vez creado los o el acceso directo podremos ejecutar la aplicación tal y como si fuera una aplicación que haya sido instalada de manera local:

Ahora bien: ¿Cuál es la ruta de ese acceso directo? ¿A qué programa o archivo apunta?  Debemos recordar que las aplicaciones Silverlight son un archivo con extensión .XAP que no es más que un archivo .ZIP el cual incluye todo lo necesario para ejecutarse, pero NO es un ejecutable per sé, no es un tipo de archivo que el Sistema Operativo entienda como ejecutable.

sllauncher.exe

Si vemos las propiedades del acceso directo creado al instalar la aplicación Fuera del Navegador podemos observar que es un acceso al Microsoft Silverlight Offline Launcher o sllauncher.exe.  Este aplicativo permite la ejecución de aplicaciones .XAP de Silverlight ya que *emula* precisamente el comportamiento de un Navegador.

El sllauncher.exe recibe como parámetro el identificador de la aplicación a ejecutar, en el caso de este artículo “localhost.0” es el identificador.  El identificador de la aplicación o AppID está compuesto por <nombre del dominio>.<secuencia> en donde “secuencia” es el número de aplicaciones que has instalado de ese dominio, es decir, la siguiente aplicación Fuera del Navegador sería localhost.1 la siguiente localhost.2 y así sucesivamente.

Ejecutemos la aplicación Fuera del Navegador utilizando el acceso directo.

Un hecho importante es que esa aplicación es una instancia diferente a la instancia que se está ejecutando en el Navegador, esto debido a que cuando “instalamos” una aplicación de Silverlight Fuera del Navegador esa aplicación es colocada en un fólder especial en la siguiente ruta:

C:\Users\<Nombre del Usuario>\AppData\LocalLow\Microsoft\Silverlight\Offline\<Identificador de la aplicación>

Asimismo no debemos perder de vista que aunque la aplicación esté ejecutándose afuera de un Navegador, la aplicación sigue estando en un sandbox de baja confianza.  Esto significa que si bien nuestras aplicaciones de Silverlight 3 están “viviendo” en el equipo del cliente no pueden tener acceso a recursos fuera de ese sandbox, por ejemplo no pueden tener acceso a los puertos del equipo, ejecutar ensamblados que requieran permisos especiales y un largo etcétera.  Esta característica es hoy en día motivo de polémica ya que muchas personas les gustaría ver a Silverlight 3 con todos los permisos como cualquier aplicación local.  En mi particular punto de vista esto sería contraproducente por motivos de riesgos en la seguridad así como también por el hecho que Silverlight está pensado para hacer aplicaciones tipo RIA, distribuibles a través de la Web.  En todo caso para eso tenemos al alcance de nuestra mano WPF y/o otras tecnologías, claro está, no son multi-plataforma como lo es Silverlight pero ese es tema de otro artículo.

Metadatos

Es en este fólder donde precisamente vamos a encontrar el archivo .XAP junto con otros archivos de metadatos creados automáticamente por el runtime de Silverlight 3 para poder ejecutar esa aplicación Fuera del Navegador.  El archivo metadata que encontramos en este fólder incluye información acerca de la aplicación como la fuente original del archivo .XAP, en qué archivo HTML hospedar la aplicación Silverlight, el título y descripción de la aplicación y el AppID:

LaunchPath=C:\Users\Rodrigo\AppData\LocalLow\Microsoft\Silverlight\ Offline\localhost.0\index.html
CustomIcon=1
SourceDomain=localhost
OriginalUri=http://localhost:6495/ClientBin/DevMasters.Games.SLFred .xap
AppID=localhost.0
Description=Este es un sencillo juego de memoria que se asemeja al  Fabuloso Fred, famoso juego en la década de los 80's
Title=Silverlight Fred Fuera del Navegador
Name=Silverlight Fred

Y hablando precisamente del archivo HTML que hospedará la aplicación .XAP, podemos darnos cuenta que no es más que un archivo HTML normal, que incluye el elemento <object> para instanciar el plugin de Silverlight.  La fuente del plugin de Silverlight tiene la sintaxis offline://<app ID> tal y como lo muestra el siguiente fragmento de código tomado del archivo index.html; generado automáticamente por Silverlight al “instalar” nuestra aplicación Fuera del Navegador:

<object data="data:application/x-silverlight," type="application/x-silverlight" width="100%" height="100%">
    <param name="source" value="offline://localhost.0"/>
    <param name="background" value="white" />
    <a href="https://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">
        <img src="https://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
    </a>
</object>

Un punto que en lo personal espero ver en las próximas versiones de Silverlight 3 es la posibilidad de personalizar este archivo HTML y tener más control sobre él ya que por el momento es creado automáticamente sin intervención alguna del usuario o de los desarrolladores.  Esperemos que así suceda en un futuro.

Almacenamiento Aislado

Ya que la capacidad Fuera del Navegador de Silverlight 3 está pensada para un escenario de aplicaciones desconectadas o probablemente frecuentemente desconectadas el Almacenamiento Aislado de Silverlight 3 para las aplicaciones Fuera del Navegador es aumentado automáticamente de 1MB a 25MB, esto con el objetivo de permitir a nosotros los desarrolladores el tener más espacio para guardar datos para efectivamente permitir un escenario offline, sin necesidad de solicitar un incremento del tamaño del espacio al usuario final.  Nota:  Estos 25MB no son regresados a 1MB cuando *desinstalamos” la aplicación Fuera del Navegador.  Este es un comportamiento de la versión Beta 1 de Silverlight 3 y probablemente cambie en próximas versiones.

También debemos tomar en cuenta un punto muy importante:  tanto la aplicación Fuera del Navegador (fuera de línea) como su versión Dentro del Navegador (en línea) utilizan el mismo Almacenamiento Aislado, un hecho bastante importante para escenarios de sincronización una vez re-establecida la conexión de la aplicación, o para guardar configuración, estado, etc.

El Puente HTML y las aplicaciones Fuera del Navegador

Si tu aplicación de Silverlight 3 en el Navegador utiliza el Puente HTML (el componente de Silverlight que sirve para comunicarnos al DOM), esta característica está deshabilitada de manera predeterminada en las aplicaciones Fuera del Navegador de Silverlight 3 Beta 1.  Si ejecutan algún método del Puente HTML (implementado en la clase HtmlPage), causará una excepción con el siguiente mensaje de error:

AHORA bien, SÍ podemos habilitar el Puente HTML editando directamente el archivo index.html, agregando simplemente el parámetro enablehtmlaccess y establecerlo a true.  En este caso sllauncher.exe se comporta como cualquier Navegador ya que es capaz de entender la funcionalidad de los métodos que la clase HtmlPage expone; tanto navegar a una página Web por medio de HtmlPage.Window.Navigate() como crear elementos HTML de manera dinámica como la siguiente ilustración lo demuestra:

El código del botón para demostrar que sí podemos habilitar el Puente HTML si lo forzamos es el siguiente:

try
{
    HtmlElement newDiv = HtmlPage.Document.CreateElement("div");
    newDiv.SetAttribute("innerHTML", "Creado desde .NET!");
    newDiv.SetStyleAttribute("background", "Cyan");
    HtmlPage.Document.Body.AppendChild(newDiv);
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

Una cuestión que aún no logro descifrar es que si sllauncher.exe es Internet Explorer sin cromo (menús, borde, etc.) ya que incluso si ejecuto la siguiente línea en mi aplicación:

HtmlPage.Window.Navigate(new Uri("http://www.microsoft.com", UriKind.RelativeOrAbsolute), "_blank");

El Navegador que abrirá esta página es IE y no FireFox.  Espero que a corto plazo nuestros buenos amigos de Microsoft puedan aclararnos exactamente este comportamiento.

Actualización

Una aplicación Fuera del Navegador no requiere una conexión para ejecutar, ya que como su nombre lo indica está pensada para operar fuera de línea y estar en espera a que la conexión se restablezca.  Cuando hay una conexión disponible, la aplicación al ser ejecutada irá al servidor a buscar si hay una nueva versión disponible.  Si efectivamente hay una versión más nueva el archivo .XAP más reciente es copiado del servidor al cliente sin intervención alguna por parte de los usuarios; además de esto un evento es levantado en la aplicación para indicar que hay una nueva versión y de esa manera indicar al usuario que no está ejecutando la última versión.  El evento se llama ExecutionStateChanged y está implementado en la clase Application.  Una vez levantado este evento es conveniente consultar la propiedad ExecutionState la cual tendrá el valor ExecutionStates.DetachedUpdatesAvailable en este caso.  La nueva versión será ejecutada la próxima vez que la aplicación sea iniciada.

Una cosa más al respecto:  por el momento en Silverlight 3 Beta 1 no hay manera de evitar la descarga de la nueva versión de la aplicación; no obstante esto es probable que sea modificado en próximas versiones de la plataforma.  Lo ideal sería preguntar al usuario si desea actualizar efectivamente la aplicación o no; dejando esta opción al buen criterio y al tiempo que tengan los usuarios en ese momento.

Depuración

Ya que la aplicación Fuera del Navegador es hospedada en sllauncher.exe, debemos adjuntarnos a este proceso si deseamos depurar nuestra aplicación.  La siguiente figura muestra cómo el código es alcanzado una vez adjuntándonos a dicho proceso desde Visual Studio.  El código que es alcanzado es la excepción que se obtiene al utilizar los métodos de la clase HtmlPage (sin haber forzado su habilitación como se explica en este mismo artículo):

Desinstalación

Al hacer clic-secundario sobre la aplicación ya sea en el Navegador o en sllauncher.exe se nos presenta la opción para removerla.  Al hacer clic todos los accesos directos creados por la instalación son borrados así como el contenido del fólder de la aplicación localizado en C:\Users\<Nombre del Usuario>\AppData\LocalLow\Microsoft\Silverlight\Offline\<Identificador de la aplicación>.  Como lo comenté antes, al remover una aplicación Fuera del Navegador los 25MB de del Almacenamiento Aislado no son regresados a 1MB; este es el comportamiento que tiene Silverlight 3 Beta 1 en estos momentos pero podrá ser modificado en futuras versiones.

Resumen

La posibilidad de ejecutar nuestras aplicaciones de Silverlight afuera del Navegador nos brinda muchas nuevas oportunidades para el desarrollo de aplicaciones que usen esta plataforma.  Aplicaciones totalmente o frecuentemente desconectadas que puedan ser operables de manera local y que puedan sincronizar sus datos o estado en el momento que haya una conexión disponible es motivo suficiente para tomar Silverlight como plataforma de desarrollo robusta, confiable y ligera: una plataforma que puede llegar allá donde no han llegado otras tecnologías de Microsoft.