viernes, 13 de septiembre de 2013

Gestión de versiones en el GAC

Cuando se desarrolla una librería para ser distribuida públicamente es normal que esta pueda tener actualizaciones de versiones. Bien porque corrige algunos fallos o porque introduce nueva funcionalidad. Sobre el sistema de versionados ya hablé en un post anterior.

En esta ocasión me quiero centrar en las actualizaciones automáticas de estos ensamblados de las librerías en el GAC. Me explico con un ejemplo. Supongamos que hemos publicado una librería (v1.0.0.0) para que pueda ser usada por múltiples aplicaciones y componentes. Sacamos una nueva versión que corrige algunos errores (v1.0.0.1) y que mantiene la compatibilidad con la versión anterior.

Al ir firmadas con un Strong Name, las aplicaciones ignoran la nueva versión por completo, obligando a que estas deban ser recompiladas haciendo referencia a la nueva versión. Estamos dejando en manos de los desarrolladores que usan nuestras librerías la tarea de actualizar sus aplicaciones a la nueva versión. Si el número de aplicaciones es grande o el problema solucionado es grave (supongamos un agujero de seguridad), el escenario no es muy halagüeño.

Lo ideal es que las aplicaciones se adapten automáticamente a las nuevas versiones de ensamblados sin que a priori se necesite la re-compilación de las aplicaciones. Y digo a priori porque deben ser los desarrolladores de las aplicaciones los que establezcan si realmente quieren este comportamiento o no.

Redirección de versiones de ensamblado

.Net nos permite este tipo de políticas a través de su redirección de ensamblados. Esto es, podemos indicar a una aplicación que use versiones más modernas de un ensamblado.

Este tipo de políticas se pueden realizar en 3 niveles:

  • A nivel de aplicación. Cada aplicación decide su política de actualizaciones. Es decir, que versión van a usar en caso de que haya varias versiones del mismo ensamblado, o si realmente no quieren que esta política se lleve a cabo.
  • A nivel de máquina. Este es poco frecuente de usar. Normalmente el administrador de la máquina decide si se debe usar una versión concreta o no de un ensamblado en las aplicaciones instaladas que la usan.
  • A nivel de proveedor. Los proveedores de las librerías definen en el GAC la política de versiones a usar. De manera que cuando deciden que dos versiones son compatibles, las aplicaciones usarán automáticamente la versión más moderna. Aun así, se puede indicar que una aplicación no siga esta política y que continúe usando la versión de ensamblado con la que fue creado.

En los tres niveles, el esquema para definir la política de redirección se realiza de la misma manera a través de XML:

image

PublicherPolicyFile.xml

  • <assemblyBinding> define el bloque de redirección y sólo puede haber uno por fichero de configuración.
  • <dependantAssembly> puedes tener tantos bloques como necesites aunque cada uno sólo debe contener un elemento <assemblyIdentity>.
  • <assemblyIdentity> define el nombre del ensamblado a redireccionar y su publicKeyToken para poder ser identificado sin que haya ninguna ambigüedad.   
  • <bindingRedirect> define la redirección de la versión. en la parte de oldVersion soporta tanto una versión en concreto (como es el caso del ejemplo) como un rango de versiones.

    No es necesario indicar de manera individual cada una de las versiones que queremos redirigir. También podemos indicar rangos de versiones y comodines:

  • image

    Si queremos usar la política de actualizaciones a nivel de aplicación, basta con poner la configuración en el fichero de configuración de la aplicación tal y como se muestra en el código XML anterior.

    En caso de ser nosotros los que distribuyamos las librerías, necesitaremos crear un fichero de políticas de versionado a nivel de proveedor. A continuación se explica cómo hacerlo.

    Crear un fichero de políticas de proveedor

    La creación de este fichero de políticas pasa por 3 sencillos pasos:

    1. Crear el fichero XML con la configuración de la política. Básicamente como se hizo en el ejemplo anterior.
    2. Crear el ensamblado con la configuración de la política.
    3. Añadir el ensamblado con la política de redirección al GAC.

    El paso 1 es básicamente crear el fichero tal y como se define en el XML del ejemplo, donde para el ensamblado ArriviSoft.RedirectingAssembllies.Library se ha definido que todos aquellas aplicaciones que referencien a la versión 1.0.0.0, pueden utilizar la versión 1.0.0.1

    Para crear el ensamblado que contendrá la política de redirección debemos usar la herramienta Assembly Linker (al.exe) que viene con Visual Studio.

    Ejecutamos el siguiente comando:

    al.exe /link:PublisherPolicyFile.xml  /out:Policy.1.0.ArriviSoft.RedirectingAssemblies.MyLibrary.dll  /keyfile:ArriviSoft.snk  /platform:x86

    donde:

    • /link: Indica el fichero xml con la política de redirección de ensamblados.
    • /out: Indica el ensamblado que se va a generar y que contendrá la política de redirección. Atención con el formato de nombre de fichero pues debe ser:
      "Policy.majorVersion.minorVersion.NombreEnsamblado.dll"
    • /keyfile: Fichero con el par de claves que además debe ser el mismo con el que se firme el ensamblado.
    • /platform: Permite definir la plataforma de compilación (x86, amd64, ia64, o MSIL) para afinar mejor.
      Desgraciadamente no podremos generar el mismo ensamblado de políticas si definimos distintas plataformas dado que el nombre del ensamblado resultante sería el mismo. Para solucionarlo bastaría con indicar la plataforma dentro del propio nombre de ensamblado.

    Finalmente, una vez tengamos el ensamblado con la política de redirección, este ya puede ser usado en los equipos clientes. El instalador de nuestra librerías debe registrar en el GAC la nueva versión de ensamblados junto con el ensamblado de políticas usando el comando Global Assembly Cache tool (Gacutil.exe)