Click here to Skip to main content
15,891,248 members
Articles / Programming Languages / Visual Basic

Using Installutil to install a Windows Service and passing it parameters for the service

Rate me:
Please Sign up or sign in to vote.
1.31/5 (5 votes)
29 Apr 2008CPOL2 min read 79.3K   1.7K   14  
Pass parameters to InstallUtil so that it will use them when it installs the service into the Service Control Manager
Imports System.ComponentModel
Imports System.Configuration.Install
Imports System.Collections

''' <summary>
''' Public class inherited from System.Configuration.Install.Installer.  Provides the base functionality
''' to install any services that are constructed using the ProcessorBase class that this installer class 
''' is part of.
''' </summary>
''' <remarks>This class provides extra parameter processing that extends the basic Installer class.  To see the details,
''' either run the InstallUtil with the /usage parameter, or view the code for the DisplayHelp method.
''' This class accepts (requires) 3 parameters to install the windows service: NAME, DISPLAYNAME, and DESCRIPTION.
''' </remarks>
<System.ComponentModel.RunInstaller(True)> Public Class ServiceInstallerBase
    Inherits System.Configuration.Install.Installer

    Private ServiceProcessInstaller1 As System.ServiceProcess.ServiceProcessInstaller
    Private ServiceInstaller1 As System.ServiceProcess.ServiceInstaller

    Public Sub New()
        MyBase.New()

        Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller
        Me.ServiceInstaller1 = New System.ServiceProcess.ServiceInstaller

        '
        'ServiceProcessInstaller1
        '
        Me.ServiceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService
        Me.ServiceProcessInstaller1.Password = Nothing
        Me.ServiceProcessInstaller1.Username = Nothing
        '
        'ServiceInstaller1
        '
        Me.ServiceInstaller1.Description = "Service for Testing the Installer.Context Property"
        Me.ServiceInstaller1.DisplayName = "Test Service Installer"
        Me.ServiceInstaller1.ServiceName = "TestService"

        Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})

    End Sub

    ''' <summary>
    ''' Overriden method of the base class that logs messages to the console/log file.
    ''' </summary>
    ''' <param name="stateSaver">IDictionary parameter that is used to collect changes made durring the
    ''' installation process.</param>
    ''' <remarks>This method can be further extended if need be to do more in-depth logging or to 
    ''' set the account used by the service.  </remarks>
    Public Overrides Sub Install(ByVal stateSaver As System.Collections.IDictionary)

        Log("In Install Method - Context parameters verified, install continuing")
        Log("")
        MyBase.Install(stateSaver)

        Log("In Install Method - Finished installing the service...")
        Log("")

    End Sub

    ''' <summary>
    ''' Overriden method of the base class that logs messages to the console/log file.
    ''' </summary>
    ''' <param name="savedState">IDictionary parameter that is used to collect changes made durring the
    ''' installation process.</param>
    ''' <remarks>This method does nothing more then add a few messages and then call the base class.</remarks>
    Public Overrides Sub Uninstall(ByVal savedState As System.Collections.IDictionary)

        Console.WriteLine("In UnInstall Method - Context parameters verified, uninstall continuing")
        Console.WriteLine()
        Console.WriteLine("In UnInstall Method - Now UnInstalling the service...")
        Console.WriteLine()

        MyBase.Uninstall(savedState)
    End Sub

    ''' <summary>
    ''' Verifies that the required parameters are in place
    ''' </summary>
    ''' <param name="savedState">IDictionary parameter used to save the install/unistall state information.</param>
    ''' <remarks>To uninstall the service, only the service name is required.  But it maust be the service
    ''' name, not the display name.  The properties dialog of the Service control applet shows this value.</remarks>
    Protected Overrides Sub OnBeforeUninstall(ByVal savedState As System.Collections.IDictionary)
        MyBase.OnBeforeUninstall(savedState)
        Dim bMissing As Boolean = False
        Dim sServiceName As String = ""
        Dim sServiceDescription As String = ""
        Dim sServiceDisplayName As String = ""


        Log("In BeforeUnInstall Method - Checking for required context parameters.")

        If Me.Context.IsParameterTrue("logtoconsole") Then
            Log("The property has the following " & Me.Context.Parameters.Count & " parameters in it: ")
            For Each sKey As String In Me.Context.Parameters.Keys
                Log("   Key: " + sKey + "  has the value " + Me.Context.Parameters.Item(sKey))
            Next

            Log("In OnBeforeUnInstall Method - End of all context parameters.")
        End If
        Log("")

        If Not Me.Context.Parameters.ContainsKey("name") Then
            Log("In OnBeforeUnInstall Method - Context parameter NAME not found!")
            bMissing = True
        End If

        If bMissing Then
            Log("In OnBeforeUnInstall Method - Service name parameter not specified, UnInstall aborted!")
            Throw New InstallException("Service UnInstaller - Service name parameter not specified, use /usage for more information.")
            Log("e.g. InstallUtil /logtoconsole=false /usage <path/service.exe>")
            Exit Sub
        End If

        sServiceName = Me.Context.Parameters.Item("name")
        sServiceDescription = ""
        sServiceDisplayName = ""

        'Now test if we can change the Service Name or Description in here
        Me.ServiceInstaller1.ServiceName = sServiceName
        Me.ServiceInstaller1.Description = sServiceDescription
        Me.ServiceInstaller1.DisplayName = sServiceDisplayName
        Log("In OnBeforeUnInstall Method - Context parameter(s) verified, Continuing with uninstall!")
    End Sub

    ''' <summary>
    ''' Verifies that all required parameters are present and updates the process and service 
    ''' installer components with the supplied NAME, DISPLAYNAME, and DESCRIPTION.
    ''' </summary>
    ''' <param name="savedState">IDictionary parameter containg the details of the installation.</param>
    ''' <remarks>This procedure does not change or modify the base functionality, and thus it does 
    ''' nothing with thesavedState parameter.  It merely checks that the required parameters are in the
    ''' collection contained in the Context parameter.  If they are found, it will update the properties
    ''' of the 2 installer componets with the supplied parameters.  See the DisplayHelp procedure for 
    ''' more information.</remarks>
    Protected Overrides Sub OnBeforeInstall(ByVal savedState As System.Collections.IDictionary)
        MyBase.OnBeforeInstall(savedState)
        Dim sServiceName As String = ""
        Dim sServiceDescription As String = ""
        Dim sServiceDisplayName As String = ""
        Dim bMissing As Boolean = False

        If Me.Context.Parameters.ContainsKey("USAGE") Then
            DisplayHelp()
            Throw New InstallException("Service Installer has exited, rerun when ready.")
            Exit Sub
        End If
        Log("In OnBeforeInstall method - Now obtaining the installer's context property...")
        If Me.Context.IsParameterTrue("logtoconsole") Then
            Log("The property has the following " & Me.Context.Parameters.Count & " parameters in it: ")
            For Each sKey As String In Me.Context.Parameters.Keys
                Log("   Key: " + sKey + "  has the value " + Me.Context.Parameters.Item(sKey))
            Next

            Log("In OnBeforeInstall Method - End of all context parameters.")
        End If

        Log("")
        Log("In OnBeforeInstall Method - Checking for required context parameters.")

        If Not Me.Context.Parameters.ContainsKey("name") Then
            Log("In OnBeforeInstall Method - Context parameter NAME not found!")
            bMissing = True
        End If

        If Not Me.Context.Parameters.ContainsKey("displayname") Then
            Log("In OnBeforeInstall Method - Context parameter DISPLAYNAME not found!")
            bMissing = True
        End If

        If Not Me.Context.Parameters.ContainsKey("description") Then
            Log("In OnBeforeInstall Method - Context parameter DESCRIPTION not found!")
            bMissing = True
        End If

        If bMissing Then
            Log("In OnBeforeInstall Method - Context parameter(s) not specified, Install aborted!")
            Log("Service Installer - Missing Required Parameters, use /usage for more information.")
            Log("e.g. InstallUtil /logtoconsole=false /usage <path/service.exe>")
            Log("")
            Throw New InstallException("Service Installer - Missing Required Parameters, use /usage for more information.")
            Exit Sub
        End If

        sServiceName = Me.Context.Parameters.Item("name")
        sServiceDescription = Me.Context.Parameters.Item("description")
        sServiceDisplayName = Me.Context.Parameters.Item("displayname")

        'Now test if we can change the Service Name or Description in here
        Me.ServiceInstaller1.ServiceName = sServiceName
        Me.ServiceInstaller1.Description = sServiceDescription
        Me.ServiceInstaller1.DisplayName = sServiceDisplayName
        Log("In OnBeforeInstall Method - Context parameter(s) verified, Continuing with install!")
    End Sub

    ''' <summary>
    ''' Displays the usage screen if the parameter /usage is found on the command line.
    ''' </summary>
    ''' <remarks>This procedure assumes that InstallUtil was used to invoke the installer class of the 
    ''' service executable file.  If the /usage parameter was detected on the command line, then this
    ''' procedure will print (to the console) the usage information for the class.
    ''' e.g. USAGE: InstallUtil /u /logtoconsole=true|false /usage /NAME={servicename} /DISPLAYNAME={"Display Name"} /DESCRIPTION={"Description of Service"} Service.Exe
    ''' </remarks>
    Private Sub DisplayHelp()
        Log("")
        Log("")
        Log("USAGE: InstallUtil /u /logtoconsole=true|false /usage /NAME=<servicename> /DISPLAYNAME=<""Display Name""> /DESCRIPTION=<""Description of Service"" Service.Exe")
        Log("")
        Log("WHERE: /u             means to uninstall the service contained in the EXE file")
        Log("                      and described by the following parameters.")
        Log("       /logtoconsole  is true or false to control displaying the full")
        Log("                      output of the installer.")
        Log("       /usage         will output this help screen.  If used it requires no other")
        Log("                      parameters besides the service.exe file")
        Log("       <servicename>  is less then 33 characters, contains only alpha-numeric")
        Log("                      characters and has no space characters.")
        Log("       <Display Name> is less then 51 characters and contains only alpha-numeric")
        Log("                      characters. You must quote any space characters.")
        Log("       <Description>  is less then 256 characters, contains only alpha-numeric")
        Log("                      characters. You must quote any space characters.")
        Log("       Service.exe    is the full path and file name of the new service you")
        Log("                      want to install.")
        Log("")
        Log("NOTE: The -u option requires only the service name,")
        Log("      but it must be the exact case sensitive name of the service, ")
        Log("      as it appears in the properties page of the Control panel Services applet.")
        Log("      It is NOT the display name, it must be the service name.")
        Log("")
        Log("EXAMPLE:")
        Log("InstallUtil /logtoconsole=false /NAME=TestService /DISPLAYNAME=""Test Display Name"" /DESCRIPTION=""Test Service Description"" C:\Windows\System32\TestService.exe")
        Log("")
        Log("")
    End Sub

    ''' <summary>
    ''' Displays the supplied message string on the screen and in the associated log file.
    ''' </summary>
    ''' <param name="sMsg">String containing the message to be logged</param>
    ''' <remarks>If console logging is turned on the procedure will call the base class's LogMessage
    ''' method which will output to both the log file and the console.  If console logging is turned off
    ''' (logtoconsole=false), the procedure will override it by using Console.WriteLine, however the 
    ''' message is still recorded in the base installer's log file.</remarks>
    Private Sub Log(ByVal sMsg As String)
        If Me.Context.IsParameterTrue("logtoconsole") Then
            Me.Context.LogMessage(sMsg)
        Else
            Me.Context.LogMessage(sMsg)
            Console.WriteLine(sMsg)
        End If
    End Sub
End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Allstream ITS
Canada Canada
Senior software architect and developer for 18 years. Worked primarily with microsoft products, using them to integrate many 3rd party systems from numerous vendors into cohesive systems.

Comments and Discussions