Thursday, May 24, 2007

How to create an installer using WIX which installs a Windows Service?

This tutorial walks you through how to create an installer using WIX which installs a Windows Service.

1) Create a configuration file that specifies the supported frameworks, named it WixWinServiceConfig.xml.



<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v2.0.50727"/>
</startup>
</configuration>

2) Put your InstallUtilLib.dll, SampleWindowsService.exe (EXE of Windows Service) and WixWinServiceConfig.xml in a folder (I placed these files in folder that contains candle.exe and light.exe for simplicity). You can find the InstallUtilLib.dll in your %windir%\Microsoft.NET\Framework\v2.0.50727\ directory. Once you have these three files, you can start coding the WXS file.

3) Create a wxs file named WindowsServiceWixProject.wxs. For full code refer Appendix.
InstallUtilLib.dll added in wxs file as a binary. This file does all the works of installing the services.

To perform a managed install of the service, you need four custom actions - two deferred custom actions for installing and uninstalling, one commit custom action and one rollback custom action. As these custom actions execute in the higher security context, you need to pass data to these custom actions using four separate 'Set Property' custom actions.

To maintain the sequence of actions, <installexecutesequence> is used in wxs file.

4) After creating the WindowsServiceWixProject.wxs file, compile it with candle.exe. After compilation WindowsServiceWixProject.wixobj file gets created. Then link the WindowsServiceWixProject.wixobj file with light.exe. This results in the creation of WindowsServiceWixProject.msi file.


Figure 1: Compliation and Link of Wix's files

5) To install the msi installer, run following command
msiexec /i WindowsServiceWixProject.msi


Figure 2: Installation of msi file

6) To uninstall the msi installer, run following command
msiexec /uninstall WindowsServiceWixProject.msi


Figure 3: Uninstallation of msi file


Figure 4: Uninstallation of msi file


Figure 5: Uninstallation of msi file

Appendix


WindowsServiceWixProject.wxs




<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="182a4509-6086-4eed-b1e7-b155aa1e7ea5" Name="DotNetService"
Language="1033" Version="1.0.0.0" Manufacturer="Persistent"
UpgradeCode="49c8c75a-5210-4944-b2b8-69814e6a874d">
<Package InstallerVersion="200" Compressed="yes" />

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

<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='DOTNETSERVICE' Name='DotNet'>
<Component Id='TheService' Guid='a464e2d9-a75e-4996-9f54-fd5155c3c35a'>
<File Id='WindowsService' Name='SampleWindowsService.exe'
KeyPath='yes' DiskId='1' Source='SampleWindowsService.exe' />
<File Id='ConfigFile' Name='WixWinServiceConfig.xml' DiskId='1'
Source='WixWinServiceConfig.xml' CompanionFile='WindowsService'/>
</Component>
</Directory>
</Directory>
</Directory>

<Feature Id='TheOnlyFeature' Description='Feature contains the single component' Level='1'>
<ComponentRef Id='TheService'/>
</Feature>

<!-- Including the InstallUtilLib.dll. This file does all
the works of installing the services. -->
<Binary Id='InstallUtil' SourceFile='InstallUtilLib.dll' />

<!--Write custom actions to install, uninstall, commit and rollback the changes-->
<CustomAction Id='InstallServiceSetProp' Property='InstallService' Value='/installtype=notransaction /action=install /LogFile= "[#WindowsService]" "[DOTNETSERVICE]WixWinServiceConfig.xml"'/>
<CustomAction Id='InstallService' BinaryKey='InstallUtil'
DllEntry='ManagedInstall' Execute='deferred' />

<CustomAction Id='UnInstallServiceSetProp' Property='UnInstallService' Value='/installtype=notransaction /action=uninstall /LogFile= "[#WindowsService]" "[DOTNETSERVICE]WixWinServiceConfig.xml"'/>
<CustomAction Id='UnInstallService' BinaryKey='InstallUtil'
DllEntry='ManagedInstall' Execute='deferred' />

<CustomAction Id='CommitServiceSetProp' Property='CommitService' Value='/installtype=notransaction /action=commit /LogFile= "[#WindowsService]" "[DOTNETSERVICE]WixWinServiceConfig.xml"'/>
<CustomAction Id='CommitService' BinaryKey='InstallUtil'
DllEntry='ManagedInstall' Execute='commit' />

<CustomAction Id='RollbackServiceSetProp' Property='RollbackService' Value='/installtype=notransaction /action=rollback /LogFile= "[#WindowsService]" "[DOTNETSERVICE]WixWinServiceConfig.xml"'/>
<CustomAction Id='RollbackService' BinaryKey='InstallUtil'
DllEntry='ManagedInstall' Execute='rollback' />

<!-- Now to sequence these Custom Actions in the execute sequence -->

<InstallExecuteSequence>

<Custom Action='UnInstallServiceSetProp' After='MsiUnpublishAssemblies'>$TheService=2</Custom>
<Custom Action='UnInstallService' After='UnInstallServiceSetProp'>$TheService=2</Custom>

<Custom Action='InstallServiceSetProp' After='StartServices'>$TheService>2</Custom>
<Custom Action='InstallService' After='InstallServiceSetProp'>$TheService>2</Custom>

<Custom Action='RollbackServiceSetProp' After='InstallService'>$TheService>2</Custom>
<Custom Action='RollbackService' After='RollbackServiceSetProp'>$TheService>2</Custom>

<Custom Action='CommitServiceSetProp' After='RollbackService'>$TheService>2</Custom>
<Custom Action='CommitService' After='CommitServiceSetProp'>$TheService>2</Custom>

</InstallExecuteSequence>
</Product>
</Wix>






WixWinServiceConfig.xml





<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v2.0.50727"/>
</startup>
</configuration>




Suggested Links:

1) Installing Windows Services (Created with .NET) with WIX---

http://blog.vagmim.com/2004/09/installing-windows-services-created.html

4 comments:

Rocker!! said...

While running the msi after creating this way throws out an assembly manifest error.Also the installutil.lib stuff is out dated and not recommended.right way is to use ServiceInstall and ServiceControll components to create a service..

Anonymous said...

Nvin Installer is a simple installer developed using WiX toolset. It is really useful if somebody don't want scratch their head to create MSI files.

Ayyanar said...
This comment has been removed by the author.
yiannisf said...

Is there a way to delete the WixWinServiceConfig.xml file and then adding it back before uninstalling so that it can be used again by the custom action that uninstalls the service?

Google