En la mayor parte de mis proyectos últimamente, estoy creando los setups con WiX, que la verdad es que es muy potente a la hora de crear setups, aunque su curva de aprendizaje es realmente empinada …
Sin embargo, con sólo tener el msi del instalable no siempre es suficiente, cuando vasa distribuir software que tiene dependencias externas, como por ejemplo, el propio .NET Framework, necesitamos, antes de instalar nuestro software, asegurarnos que el cliente tiene instaladas estas dependencias.
Aquí es dónde entran los “bootstrappers”, que básicamente son un envoltorio de nuestro msi, que verifica antes que las dependencias externas, y si no las tiene las instala.
Para este post me voy a basar en las dependencias de Microsoft, que las tenemos disponibles en el directorio de SDK cuando instalamos el propio Visual Studio 2008, si miráis en %Program Files%\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages podéis ver los paquetes de dependencias que tenéis disponibles en vuestra máquina (comrpbadlo también en la máquina de Team Build de paso).
Dependiendo del tipo de paquete, algunos tendremos los ficheros instalables de las dependencias directamente, para incluirlos en nuestro setup final, además de unos ficheros Xml con todas las propiedades del paquete. Otra opción, que será la que usemos en este ejemplo, es que en vez de incluir todos los ficheros en nuestro setup (incrementando el peso final), le podemos decir, al generar el bootstrapper, que los coja de lo que llama el HomeSite que no es otra cosa que lo coja desde internet directamente (de la web de Microsoft por ejemplo) que es lo que yo siempre procuro hacer, para que los instalables sean lo más ligeros posibles (aunque necesitarán de internet).
Antes de incorporar una dependencia, quiero que miréis, en el directorio del paquete del Framework 3.5 por ejemplo, el fichero product.xml, abridlo con el bloc de notas mismamente y os vais directamente al final del fichero, dónde tenéis el siguiente Xml:
<RelatedProducts>
<DependsOnProduct Code=”Microsoft.Windows.Installer.3.1″ />
<IncludesProduct Code=”Microsoft.Net.Framework.2.0″ />
<IncludesProduct Code=”Microsoft.Net.Framework.3.0″ />
</RelatedProducts>
Esto nos especifica, que si incluimos este paquete en una de nuestros bootstrapper, tenemos dependencia de Windows Installer 3.1 (que incluiremos también en nuestro bootstrapper), y que instala el Framework 2 y el 3.
Bien, ya vemos un poco de dónde vamos a sacar las dependencias externas para nuestro setup, vamos a configurar la build.
Supongamos que ya tenemos una Team Build, que compila nuestra solución, y que tiene un proyecto de WiX en la misma, y que genera un msi con nuestro instalable. Hasta aquí todo se hace con Team Build, sin necesidad de hacer nada nuevo, más que una configuración de build que compile nuestro proyecto WiX. Y supongamos que nuestro producto requiere del framework 3.5 SP1.
Por cierto, un pequeño apunte :), el paquete para bootstrapper del .NET 3.5 SP1, NO viene por defecto con ninguna instalación de VS 2008 ni siquiera con SP1, necesitaremos instalar un Visual Studio Express con SP1 preinstalado (http://www.microsoft.com/express/download/) que si que trae este paquete. La podéis instalar en una máquina virtual, y del directorio que os he dicho anes, coger el paquete directamente (directorio DotNetFX35SP1), y copiarlo a tu maquina en en directorio de paquetes.
Vale, pues lo que vamos a hacer ahora es editar nuestra Team Build, tenemos que abrir el fichero TFSBuild.proj y lo que vamos a hacer, es, en el paso de Team Build AfterDropBuild, cuando ya tengamos todo compilado, y copiado al directorio de destino, vamos a generar el bootstrapper.
Lo primero, es decir que dependencias vamos a incluir, para esto, añadimos las siguientes líneas al fichero TFSBuild.proj, justo antes del cierre </Target>:
<ItemGroup>
<BootstrapperFile Include=”Microsoft.Net.Framework.3.5.SP1″>
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperFile>
<BootstrapperFile Include=”Microsoft.Windows.Installer.3.1″>
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperFile>
</ItemGroup>
Y, a continuación vamos a poner el código para generar el bootstrapper usando esos items:
<Target Name=”AfterDropBuild”>
<!–Bootstrapper for Manager EN–>
<GenerateBootstrapper
ApplicationFile=”MiMsi.msi”
ApplicationName=”Mi Setup”
BootstrapperItems=”@(BootstrapperFile)”
OutputPath=”$(DropLocation)\$(BuildNumber)\DirectorioDestino”
ComponentsLocation=”HomeSite”
Culture=”en”
/>
<Copy SourceFiles=”$(OutDir)\MiMsi.msi” DestinationFolder=”$(DropLocation)\$(BuildNumber)\DirectorioDestino”></Copy>
</Target>
Aquí le estamos diciendo, que después de haber copiado los ficheros compilados al directorio final, vamoa a generar un bootstrapper, para el msi llamado MiMsi.msi, le damos el nombre para mostrar en el bootstrapper (el título de la pantalla), la conlección de items que hemos creado antes, en OutputPath le damos el directorio dónde va a generar el fichero setup.exe (el bootstrapper), al decirle en ComponentsLocation el valor HomeSite, le decimos que cogerá los paquetes desde internet, y por último el idioma del bootstrapper (en este caso inglés).
Como último paso, copio nuestro msi, desde el directorio dónde lo ha compilado Team Build, hasta el directorio de destino dónde ya hemos generado el setup.exe, que lanza la instalación de las dependencias, y a continuación lanzaría nuestro msi.
Podéis ver que no es excesivamente difícil hacer nuestro propio bootstrapper, que instale primero nuestras dependencias, y a continuación nuestra aplicación. Tampoco es que sea un proceso muy sencillo (como sería deseable), pero con esto y la documentación de la tarea GenerateBootstrapper del MSDN podéis empezara crear vuestros propios bootstrapper: http://msdn.microsoft.com/en-us/library/ms164294(VS.85).aspx
Por cierto, todo esto realmente es MSBuild, yo he incluido el target en mi build de Team Build en el último paso, pero si no tenemos Team Build, y editando los ficheros .wixproj, podemos incluirlo en nuestra compilación local, creando, por ejemplo un target (cambiando lo de AfterDropBuild), llamado “Bootstrapper”, y ejecutandolo desde línea de comandos con MSBuild :
msbuild MiWix.wixproj /target:Bootstrapper
Cambiando los directorios necesarios también, lógicamente 🙂
Bueno espero que os haya sido de ayuda, aunque es un poco complejo de seguir, cualquier duda aquí me tenéis.