Datapayasadas

octubre 25, 2009

Actualizador (2da Parte)

Filed under: .Net, C#, Desarrollo — Etiquetas: , — Matías @ 12:11 am

En el artículo previo (Actualizador 1era Parte) llegamos a definir la estructura iba a tener nuestro archivo de actualizaciones, ahora solo nos falta descargar esa información, parsearla y hacer algo útil con ella.

Recuerden que el formato a utilizar en dicho archivo será el siguiente:

ruta relativa y nombre de archivo : versión

donde la primer parte antes de caracter : es la ruta relativa tanto remota como local; y la segunda es la última versión disponible.
Veamoslo con un ejemplo que va a ser más fácil de entender. Suponiendo que mi programa consiste de los siguientes archivos:

C:\Mi Programa\EjecutablePrincipal.exe
C:\Mi Programa\una_carpeta\OtroArchivo.dll
C:\Mi Programa\otro path con espacio\Lala.dll

En el servidor de actualizaciones tendríamos:

http://miservidor.algo/actualizaciones.txt
http://miservidor.algo/EjecutablePrincipal.exe
http://miservidor.algo/una_carpeta/OtroArchivo.dll
http://miservidor.algo/otro path con espacio/Lala.dll

Procesando la información

Ahora veremos como podemos obtener la información que necesitamos de ese archivo:

private const char SEPARADOR_VERSION = ':';

private static Dictionary<string, string> ObtenerVersionesOnline(string ServidorActualizaciones)
{
    Dictionary<string, string> listadoArchivos = new Dictionary<string, string>();
    WebClient clienteWeb = new WebClient();
    string actualizacionesEnCrudo;
    string[] actualizacionesPorLinea, informacionPorFila;

    try
    {
        actualizacionesEnCrudo = clienteWeb.DownloadString(ServidorActualizaciones);
        actualizacionesPorLinea = actualizacionesEnCrudo.Split(Convert.ToChar("\n"));

        foreach (var actualizacion in actualizacionesPorLinea)
        {
            string infoRuta, infoVersion;
            informacionPorFila = actualizacion.Split(SEPARADOR_VERSION);
            infoRuta = informacionPorFila[0].Trim();
            infoVersion = informacionPorFila[1].Trim();

            if (listadoArchivos.ContainsKey(infoRuta))
                continue;

            listadoArchivos.Add(infoRuta, infoVersion);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "¡Ocurrió un error al comprobar version online!", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    finally
    {
        clienteWeb.Dispose();
    }

    return listadoArchivos;
}

Como verán, el código es bastante simple: descargamos el archivo de texto con la información de las actualizaciones (en nuestro ejemplo sería http://miservidor.algo/actualizaciones.txt), lo desglosamos linea por linea, y luego a cada una la dividimos mediante el separador que habíamos elegido previamente, en éste caso fue el caracter dos puntos. De esta forma tenemos por un lado la ruta relativa (incluyendo el nombre del archivo) y por el otro el número de versión, claro, esto por cada línea. Guardamos esa información en una lista del tipo Dictionary y listo el pollo, pelada la gallina.

El siguiente paso sería utilizar esa información para compararla con las versiones locales de los archivos equivalentes.

public static bool ComprobarActualizaciones(string ServidorActualizaciones)
{
    Dictionary<string, string> listadoArchivos = ObtenerVersionesOnline(ServidorActualizaciones);

    try
    {
        foreach (var archivo in listadoArchivos)
        {
            string rutaAbsoluta = Path.Combine(Application.StartupPath, archivo.Key);

            if (File.Exists(rutaAbsoluta))
            {
                if (archivo.Value != "?")
                {
                    Version versionLocal = new Version(FileVersionInfo.GetVersionInfo(rutaAbsoluta).FileVersion);
                    Version versionRemota = new Version(archivo.Value);

                    // De esta forma podemos volver a una versión anterior en caso que encontremos
                    // algun problema importante en un actualización (luego de publicarla)
                    if (versionLocal != versionRemota)
                        return true;
                }
            }
            else
            {
                return true;
            }
        }

        return false;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "¡Ocurrió un error al comprobar actualizaciones!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return false;
    }
}

Lo que hacemos con éste método es recorrer la lista de actualizaciones (que obtuvimos online), tratamos de encontrar el archivo local correspondiente para cada uno de ellos y comparamos la versiones, por supuesto, solo en el caso de que exista localmente. Realmente no hace falta verificar todos y cada uno de ellos, con que encontremos uno solo desactualizado ya podremos podremos devolver un valor verdadero, que implica que existe al menos una actualización.

Vale la pena notar que en vez de:

if (versionLocal != versionRemota)
    return true;

podríamos haber usado:

if (versionLocal < versionRemota)
    return true;

No lo he hecho así por una simple razón. Me ha pasado que al publicar una actualización había algo realmente mal en alguna dll incluída, algo que cambie y no me percate que lo había roto hasta que un usuario me avisa. En estos casos prefiero volver atrás una versión para esa librería particular, simplemente modificando el archivo de texto de las actualizaciones, que tener que recompilar la dll asignándole una versión superior.

Otra cosa a tener en cuenta: es posible que en algún momento, necesitemos agregar archivos que no puedan ser versionados, al menos no como .Net lo entiende, por ejemplo, una imagen o icono. En este caso, en vez de asignar una versión en la entrada correspondiente en el archivo de texto de actualizaciones, usaremos un signo de interrogación ?. De esta forma, lo único que tendremos que verificar es que el archivo local exista, sino, se considera que hace falta una actualización (lo que va a implicar una simple descarga del archivo faltante).

Continuará …

Anuncios

1 comentario »

  1. Hay que destacar que se puede adoptar cualquier otro formato para el archivo de actualizaciones. Podríamos usar XML, JSON o cualquier otro formato serializable.

    También seria bueno encriptarlo por las dudas…

    Saludos!

    Comentario por pabloide86 — octubre 26, 2009 @ 8:43 am


RSS feed for comments on this post. TrackBack URI

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Blog de WordPress.com.

A %d blogueros les gusta esto: