65.9K
CodeProject is changing. Read more.
Home

Using Single EXE to Deploy Multiple Windows Service

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (9 votes)

Aug 23, 2007

Public Domain

1 min read

viewsIcon

65811

downloadIcon

713

To set the Windows Service name in a Setup project instead of in Project Installer of the WIndows Service project

Introduction

My project required me to package one Windows Service EXE with different configuration files for different customers. This article will demostrate how to modify ProjectInstaller to support this requirement.

Background

My company has a Windows Service product. When deployed to different customers, we want to give only a simple Setup.exe (with *.msi) to the customers for easy deployment. We want to use a different name for the Windows Service being installed.

For example, for customer ABC, after setup, the name of the Windows Service would be "ABC Service".

We will package different configuration / data files using the same EXE.

Using the Code

In standard Windows Service Project Installer, the Service Name is set in Sub InitializeComponent():
Private Sub InitializeComponent()
' (other initialization code)
Me.ServiceInstaller1.ServiceName = "Service1"
'
End Sub  

The problem is that the ServiceName is hardcoded in the service.exe. Setup project will invoke the Project Installer in the service.exe and use Service1 as the Windows Service name. We want to choose the name in the Setup project instead.

Hence, we add some code to handle BeforeInstall and BeforeUninstall events.

    ' Force Setup project to specify the service name in CustomActionData 
    ' in "Install" Custom Install Action Developer should set the same name 
    ' in CustomActionData in "Uninstall" Custom Install Action
    Private Sub DoBeforeInstall(ByVal Sender As Object, 
        ByVal Args As System.Configuration.Install.InstallEventArgs) 
        Handles MyBase.BeforeInstall
        ' Context when Install
        If GetContextParameter("SERVICENAME") = "" Then
            Throw New Exception("SERVICENAME undefined")
        End If
        If Not Me.ServiceInstaller1 Is Nothing Then
            Me.ServiceInstaller1.DisplayName = GetContextParameter(
                "SERVICENAME")
            Me.ServiceInstaller1.ServiceName = GetContextParameter(
                "SERVICENAME")
        End If
    End Sub

    ' Developer should set the same name in CustomActionData in "Uninstall" 
    ' Custom Install Action
    Private Sub DoBeforeUninstall(ByVal Sender As Object, 
        ByVal Args As System.Configuration.Install.InstallEventArgs) 
        Handles MyBase.BeforeUninstall
        ' Context when Uninstall
        If GetContextParameter("SERVICENAME") = "" Then
            Throw New Exception("SERVICENAME undefined")
        End If
        Me.ServiceInstaller1.DisplayName = GetContextParameter("SERVICENAME")
        Me.ServiceInstaller1.ServiceName = GetContextParameter("SERVICENAME")
    End Sub

    Public Function GetContextParameter(ByVal key As String) As String
        Dim sValue As String = ""
        If Me.Context Is Nothing Then
            'WriteLog("Me.ServiceInstaller1 Is Nothing")
        End If
        Try
            sValue = Me.Context.Parameters(key).ToString()
            Return sValue
        Catch
            sValue = ""
            Return sValue
        End Try
    End Function

In Setup project property, specify the [ProductName]. It will be used as the Windows Service Name (e.g. DynamicService).

In Custom Action, specify the same SERVICENAME for custom action Install and Uninstall:

Screenshot - CustomerAction.jpg

Run the setup, a Windows Service called DynamicService is installed.

Screenshot - Servicesmsc.jpg

Points of Interest

  1. For setup of multiple services on the same machine, each setup should have a different [ProductCode] and [UpgradeCode].
  2. You may also change the Windows Service description using this technique.