Monday, July 21, 2014

How to create an Installer for Windows service using Wix Installer

One of the thing I always end after creating any application is how would i deploy it, so there comes a great tool for creating installers Wix (Windows Installer XML). Creating Msi using wix is very simple at the same time they cam sometimes very complex too.

To be able to create a wix project you need to Install the Wix toolset using the link Wixtoolset
there are multiple releases available, pick most latest or which ever version you prefer. After installing the Wix tool set you would be able to see a wix project template under your visual studio.




























Creating a Windows service
Create a new project for windows service.













Write all your business logic in there of course you can add multiple C# projects related to your business and a project for data access layers too.

Now create a new project for installer








































Add the references to the Installer project
1) WixNetFxExtension
2) WixUIExtension
3) WixUtilExtension

Also add the service as reference to the Installer Project which you are trying to create msi for.



Modify the Poduct.wxs file with below given changes

       

<?xml version="1.0" encoding="UTF-8"?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"

 xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

 <Product Id="*"

    Name="Windows service name here $(var.ProductVersion)" Language="1033"

    Version="$(var.ProductVersion)" Manufacturer="Company name here"

    UpgradeCode="b454c60a-fbdf-4fb2-855a-fa4f0c73ba73">



  <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine"/>



  <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />



  <Directory Id="TARGETDIR" Name="SourceDir">

   <Directory Id="ProgramFilesFolder">

    <Directory Id="INSTALLLOCATION" Name="Service name here if you wish to have folder created with service name as installation directory (no spaces)">

    </Directory>

   </Directory>

  </Directory>



  <WixVariable Id="WixUILicenseRtf" Value="License.rtf" />

  <!-- Always install per-machine not per-user (shows up in Add/Remove for all users) -->

  <WixVariable Id="WixUISupportPerUser" Value="0" />



  <UIRef Id="WixUI_InstallDir" />





  <Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />

  <Property Id="LicenseAccepted" Value="1" />

  <Property Id="DISABLEADVTSHORTCUTS" Value="1" />



  <!-- Version Upgrade Logic -->

  <Upgrade Id="541650E3-02B3-4865-9513-712177576DC3">

   <!-- Check for an older installed version and allow it to be automatically uninstalled

      and the new version installed in its place. -->

   <UpgradeVersion

    Minimum="0.0.0" IncludeMinimum="yes" Maximum="$(var.ProductVersion)" IncludeMaximum="no" Property="NEWERPRODUCTFOUND" />

   <!-- Check for a newer installed version -->

   <UpgradeVersion Minimum="$(var.ProductVersion)" IncludeMinimum="yes" OnlyDetect="yes" Property="NEWERVERSIONDETECTED" />

  </Upgrade>



  <Condition Message="A later version of xxxx Windows Service is already installed. Setup will now exit.">

   NOT NEWERVERSIONDETECTED OR Installed

  </Condition>



  <InstallExecuteSequence>

   <RemoveExistingProducts After="InstallInitialize"/>

  </InstallExecuteSequence>

  <!-- End Version Upgrade Logic -->



  <PropertyRef Id="NETFRAMEWORK40FULL"/>

  <Condition Message="This application requires .NET Framework 4.0. Please install the .NET Framework 4.0 then run this installer again.">

   <![CDATA[Installed OR NETFRAMEWORK40FULL]]>

  </Condition>



  <!-- For now the service is always running as Network Service, so this is not needed. -->



  

  <Feature Id="ServiceFilesFeature" Title="XXXX Service" Level="1">

   <ComponentRef Id="WindowsService1.exe"/>

   <ComponentRef Id="supporting_dlls_here_if_any.dll"/>

      <ComponentRef Id="supporting_dlls_here_if_any2.dll"/>

   <!-- TODO: Remove the comments around this ComponentRef element and the Component above in order to add resources to this installer. -->

   <!-- <ComponentRef Id="ProductComponent" /> -->



   <!-- Note: The following ComponentGroupRef is required to pull in generated authoring from project references. -->

  </Feature>

 </Product>



 <Fragment>

  <DirectoryRef Id="INSTALLLOCATION">

   <Component Id="WindowsService1.exe" Guid="*">

    <File Id="WindowsService1.exe" Source="$(var.WindowsService1.TargetDir)\WindowsService1.exe" />

    <ServiceInstall Name="XXXservice" DisplayName="XXXService" Description="Dose XXX process"

          Type="ownProcess" Vital="yes" Start="auto" ErrorControl="normal">

     <util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="restart" RestartServiceDelayInSeconds="15" />

    </ServiceInstall>

   </Component>

   <Component Id="supporting_dlls_here_if_any.dll" Guid="*">

    <File Id="supporting_dlls_here_if_any.dll" Source="$(var.WindowsService1.TargetDir)\supporting_dlls_here_if_any.dll" />

   </Component>

   <Component Id="supporting_dlls_here_if_any2.dll" Guid="*">

    <File Id="supporting_dlls_here_if_any2.dll" Source="$(var.WindowsService1.TargetDir)\supporting_dlls_here_if_any2.dll" />

   </Component>

  </DirectoryRef>

 </Fragment>

</Wix>


Note: (var.ProductVersion) is defined under properties of the project.

add a file to your installer project called License.rtf
This file basically shows the license agreement when you install the msi.

Steps to create a License.rtf
1) Open MS Word
2) Type the below text in there

This software is the property of xxxx LLC.

Copyright © 2012 xxxx LLC.  All Rights Reserved.

3) Save the file as License.rtf

you can Either copy the same file and add it to your installer project or you can create a new file with in your project and add it.

see the project properties for assigning a productversion valiable



that's it compile the installer project and you would see an msi under Bin\Debug or Bin\Release fodlers.