How To Add Windows Services with WiX Installer
An important characteristic that we've highlighted in our series of posts about Windows Installer XML Toolset (WiX) is that it doesn't have a GUI. It builds the Windows Installer package with the information defined in the WiX source file (XML based).
In this article, we will show you how to add a Windows Service to your MSI package using WIX Installer.
What are the main elements needed to define a Windows Service in XML?
When it comes to defining a Windows Service in your XML, there are two elements that are mandatory and connected to each other:
- ServiceInstall element – it is used to install a Windows Service.
- ServiceControl element – it is used to control Windows Service’s behavior once installed.
Apart from these two mandatory elements, you can also use ServiceConfig to configure a service that already exists, or is being installed by the current package.
If you are not familiar with Windows Installer technology, we strongly recommend you to have a look at the corresponding MSI tables: ServiceInstall, ServiceControl, and MSIServiceConfig.
How to Add a Windows Service to Your MSI?
Now that we know the main elements, we will go through how to add a Windows Service to your MSI. We will also configure the Windows Service created and set it to “Automatic (Delayed Start)”.
This way, you can ensure that the critical Windows Services get all the resources they need at the boot time, whilst the non-critical ones start a little bit later.
Defining the ServiceInstall element
First things first, we must define our ServiceInstall element:
<ServiceInstall Id="WindowsServicesSample" Name="WindowsServicesSample" DisplayName="WindowsServicesSample" Description="Example Windows Services" Start="auto" Type="ownProcess" ErrorControl="normal" Account="LocalSystem" Arguments="/ARGUMENTS LIST" Vital="yes" Interactive="no"/>
The ServiceInstall element comes with a set of mandatory attributes that I'm listing below:
- Name – Windows Service name.
- Start – specifies when the Windows Service should be started – allowed values: “autoyes” or “demand”.
- Type – Windows Service’s type – allowed values: “ownProcess” or “shareProcess”.
- ErrorControl – specifies the behavior of the system and what action should be taken if the Windows Service cannot be installed – allowed values: “ignore”, “normal” or “critical”.
Aside from the above, other common attributes include:
- Id – the unique identifier for the Windows Service configuration (if not defined, it will default to Name attribute).
- DisplayName – the localizable name of the Windows Service used by user interface programs to identify the Windows Service.
- Description – the description of the Windows Service.
- Vital – which specifies whether the overall installation of the package should be aborted if the Windows Service fails to install – allowed values: “yes” or “no”.
- Arguments – which specifies any command-line arguments required to run the Windows Service.
- Account – which specifies the account name under which the Windows Service will run.
- Interactive – which specifies whether the Windows Service should interact with the desktop – allowed values: “yes” or “no”.
Setting the ServiceControl Element
After defining our ServiceInstall element, we can set the corresponding ServiceControl element.
<ServiceControl Id="WindowsServicesSample" Name="WindowsServicesSample" Start="install" Stop="both" Remove="uninstall" Wait="yes"/>
Just like ServiceInstall, the ServiceControl element comes with a set of mandatory attributes:
- Id – the unique identifier for the Windows Service configuration.
- Name – the Windows Service name.
Other attributes include:
- Start – which specifies whether the Windows Service should be started on install, uninstall or both – allowed values: “install”, “uninstall” or “both”.
- Stop – which specifies whether the Windows Service should be stopped on install, uninstall or both – allowed values: “install”, “uninstall” or “both”.
- Remove – which specifies whether the Windows Service should be removed on install, uninstall or both – allowed values: “install”, “uninstall” or “both”.
- Wait – which specifies whether or not to wait for Service Control Manager to report the Windows Service as complete (in “pending” state) before proceeding (maximum 30 seconds) – allowed values: “yes” or “no”.
Determine the ServiceConfig Element
Additionally, we can now go and define the ServiceConfig element to configure our Windows Service.
<ServiceConfig ServiceName="WindowsServicesSample" OnInstall="yes" DelayedAutoStart="yes"/>
The ServiceConfig element comes with the following attributes:
- Id – the unique identifier for the Windows Service configuration.
- ServiceName – the Windows Service name.
- OnInstall – which specifies whether to configure the Windows Service on the install of the parent Component – allowed values: “Yes” or “No”.
- OnUninstall – which specifies whether to configure the Windows Service on uninstall of the parent Component – allowed values: “Yes” or “No”.
- OnReinstall – which specifies whether to configure the Windows Service on reinstall of the parent Component – allowed values: “Yes” or “No”.
- DelayedAutoStart – which specifies whether a Windows Service set to “Auto-Start” should delay its start – allowed values: “Yes”/”1” or “No”/”0”.
- FailureActionsWhen – which specifies when failure actions should be applied – allowed value: “failedToStop”/”0” and “failedToStopOrReturnedError”/”1”.
- PreShutdownDelay – which specifies the time that the Service Control Manager waits after reporting a system shutdown.
ServiceConfig is only available starting with Windows Installer 5.0.
The complete listing for the WiX source file is as follows:
<?xml version="1.0" encoding="UTF-8"?> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Product Id="{2D00166E-A14A-4F24-B94F-3D5E9ED21D65}" Name="MyApp" Language="1033" Version="1.0.0.0" Manufacturer="MyCompany" UpgradeCode="{8F800905-91E8-4234-AD80-A485F156FE1B}"> <Package InstallerVersion="400" Compressed="yes" InstallScope="perMachine" /> <Media Id='1' Cabinet='MyAppCAB.cab' EmbedCab='yes' /> <Directory Id='TARGETDIR' Name='SourceDir'> <Directory Id='ProgramFilesFolder'> <Directory Id='MyCompany' Name='MyCompany'> <Directory Id='INSTALLDIR' Name='MyApp'> <Component Id='ReadmeComponent' Guid='{2D00166E-AAAA-4F24-B94F-3D5E9ED21D65}'> <File Id="Readme" Name="Readme.txt" DiskId="1" Source="Readme.txt"/> </Component> <Component Id='WindowsServicesComponent' Guid='{3D00166E-AAAA-4F24-B94F-3D5E9ED21D66}'> <File Id="WindowsServicesSample.exe" Name="WindowsServicesSample.exe" DiskId="1" Source="WindowsServicesSample.exe"/> <ServiceInstall Id="WindowsServicesSample" Name="WindowsServicesSample" DisplayName="WindowsServicesSample" Description="Example Windows Services" Start="auto" Type="ownProcess" ErrorControl="normal" Account="LocalSystem" Arguments="/ARGUMENTS LIST" Vital="yes" Interactive="no"/> <ServiceControl Id="WindowsServicesSample" Name="WindowsServicesSample" Start="install" Stop="both" Remove="uninstall" Wait="yes"/> <ServiceConfig ServiceName="WindowsServicesSample" OnInstall="yes" DelayedAutoStart="yes"/> </Component> </Directory> </Directory> </Directory> </Directory> <Feature Id='MyFeature' Title='My 1st Feature' Level='1'> <ComponentRef Id='ReadmeComponent' /> <ComponentRef Id='WindowsServicesComponent' /> </Feature> </Product> </Wix>
Compiling and building the MSI
Once we've reached this step, all you need to do is:
Pre-process and compile the WiX source file (.wxs) into an object file (.wixobj) by running the following command:
candle <path to wsx file>
Process the object file (.wixobj) and build the Windows Installer package (.msi) by running the following command:
light <path to wixobj file> –out <path to msi file>
And that’s it. Your MSI package is now built.
If you install the newly created MSI package, your Windows Service should appear in the Service Control Manager and have the following details.
As shown in the image above, I was able to set my WindowsServiceSample service to “Automatic (Delayed Start) “using the ServiceConfig element in WiX.
Windows Services in Advanced Installer
As you can see, the creation and configuration of a Windows Service using WiX are done via three elements () specifically designed for this purpose. Each element comes with its own attributes which could be a bit difficult to define, especially for those who are not that familiar with the WiX source file (XML) format.
Compared to WiX, Advanced Installer has its own dedicated GUI which you can use to create and configure a Windows Service. It is self-explanatory and it mainly consists in selecting the required configuration from a drop-down list, for each of the attributes of the 3 elements.
For more details, you could check our Services Page.