MAKEMSI quickly and reliably creates MSI files in a non-programmatic way
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
[Bottom][Contents][Prev]: ServiceControl[Next]: Shortcut
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
\->Source Code->Commands->ServiceInstall

The "ServiceInstall" Command

This command is used to install a service (it populates the MSI "ServiceInstall" table). You may also wish to use the "ServiceControl" command to manipulate the service (stop/start etc).

The service executable is indirectly specified as it is the keypath of the component associated with this entry.

You should also have a look at the "service tips" section of this manual.

Main Service Related Options

Please see the "options for commands" section of the manual.

#define? DEFAULT_SERVICE_CONTROL_INSTALL_EVENTS    STOP START
#define? DEFAULT_SERVICE_CONTROL_UNINSTALL_EVENTS  STOP DELETE
#define? DEFAULT_SERVICE_INSTALL_PROCESS           OWN
#define? DEFAULT_SERVICE_INSTALL_START             AUTO
#define? DEFAULT_SERVICE_INSTALL_ERRORS            NORMAL VITAL

The Parameters

This command takes these parameters:

Windows Installer Support is "Feeble"

You may wish or need to use other tools or mechanisms to help set up a service such as (not a complete list):

EXAMPLE

You should note that nearly all of the following code is to set up the optional recovery information.

;----------------------------------------------------------------------------
;--- Some service constants -------------------------------------------------
;----------------------------------------------------------------------------
#define MyServiceAlias         MyService
#define MyServiceDesc          My Test Service (<$MSI_MSIBASENAME>)
#define RecoveryResetInSeconds <?=6*60*60>  ;;6 hours
#( '/'
   #define RecoveryActions
   restart/5000                ;;1.  Restart after 5 seconds
   restart/60000               ;;2.  Restart after 1 minute
   restart/600000              ;;3+. Restart after 10 minutes
#)


;----------------------------------------------------------------------------
;--- Add service ------------------------------------------------------------
;----------------------------------------------------------------------------
<$DirectoryTree Key="INSTALLDIR" Dir="[ProgramFilesFolder]\MyServiceDirectory" CHANGE="\">
<$Component "<$MyServiceAlias>" Create="Y" Directory_="INSTALLDIR">
   ;--- The service EXE MUST be the keypath of the component ----------------
   <$Files ".\MyService.EXE" KeyFile="*">

   ;--- Create the service (service EXE is "KeyPath" of component) ----------
   #(
       <$ServiceInstall
                  Name="<$MyServiceAlias>"
           DisplayName="<$MyServiceDesc>"
           Description="<$MyServiceDesc>"
               Process="Own Interactive"
       >
   #)

   ;--- Control the service -------------------------------------------------
   <$ServiceControl Name="<$MyServiceAlias>" AtInstall="start stop" AtUninstall="stop delete">
<$/Component>


;----------------------------------------------------------------------------
;--- Need sc.exe available at install time (the CA below uses it) -----------
;----------------------------------------------------------------------------
<$Component "ServiceTool" Create="Y" Directory_="INSTALLDIR">
   <$Files ".\sc.exe" Comment=^This tool is used to set the services recovery options.^>
<$/Component>


;----------------------------------------------------------------------------
;--- Create script to execute "sc.exe" to set recovery options --------------
;----------------------------------------------------------------------------
#data "CaData"
   "INSTALLDIR" '[INSTALLDIR]'
#data
<$VbsCa Binary="SetServiceRecovery.vbs" DATA=^CaData^>
   ;--- INSTALL -------------------------------------------------------------
   <$VbsCaEntry "JustBeforeStartServices">
        ;--- Call generic set recovery routine ------------------------------
        SetRecovery "<$MyServiceAlias>", <$RecoveryResetInSeconds>, "<$RecoveryActions>"
   <$/VbsCaEntry>

   <?NewLine><?NewLine>
   '=========================================
   sub SetRecovery(ByVal ServiceAlias, ByVal RecoveryResetInSeconds, ByVal RecoveryActions)
   '=========================================
       ;--- Initialization --------------------------------------------------
       CaDebug 1, "Set service recovery for """ & ServiceAlias & """"
       VbsCaLogInc 1
       dim ScExe   : ScExe   = VbsCaCadGet("INSTALLDIR") & "sc.exe"
       dim ScArgs  : ScArgs  = "failure """ & ServiceAlias & """ reset= " & RecoveryResetInSeconds  & " actions= " & RecoveryActions
       dim ScArgsQ : ScArgsQ = "qfailure """ & ServiceAlias & """"

       ;--- Set the recovery information ------------------------------------
       CaDebug 2, "Setting up the services recovery options"
       VbsCaRunSync """" & ScExe & """ " & ScArgs, 0, ""  ;;Ignore RC (can't be trusted)

       ;--- Log the current state of the recovery options -------------------
       CaDebug 2, "Logging the services recovery options"
       VbsCaRunSync """" & ScExe & """ " & ScArgsQ, 0, ""

       ;--- Finished this service -------------------------------------------
       VbsCaLogInc -1
   end sub
<$/VbsCa>


;----------------------------------------------------------------------------
;--- Call the above script during install and uninstall (schedule them) -----
;----------------------------------------------------------------------------
<$VbsCaSetup Binary="SetServiceRecovery.vbs" Entry="JustBeforeStartServices" Seq="InstallServices-" CONDITION=^<$CONDITION_INSTALL_ONLY>^ DATA=^CaData^>

EXAMPLE - Complete script to run VBSCRIPT

The following script is complete but won't work unless you supply the files for the "SC.EXE" and "SrvStart.EXE" tools.

;----------------------------------------------------------------------------
;    MODULE NAME:   VbscriptBasedService.MM
;
;        $Author:   USER "Dennis"  $
;      $Revision:   1.5  $
;          $Date:   30 May 2009 15:07:16  $
;       $Logfile:   C:/DBAREIS/Projects.PVCS/Win32/MakeMsi/VbscriptBasedService.MM.pvcs  $
;      COPYRIGHT:   (C)opyright Dennis Bareis, Australia, 2003
;                   All rights reserved.
;
; DESCRIPTION
; ~~~~~~~~~~~
; Installs a Windows service which is a VBSCRIPT. You must supply the tools
; pointed to by the "SOURCEDIR_SC.EXE" & "SOURCEDIR_SRVSTART_FILES" macros.
;
; I highly recommend that you log progress so you can easly debug issues.
;
; If you output to the console it makes it easier to debug (set the
; service to be interactive).  You can also test the script like any other
; script.  You may wish to define a "test mode" to shorten or remove delays
; while testing.
;
; If you are running the VBSCRIPT like a schedule (but probably running at
; random times with possibly random delays) you should make sure that
; a trap in your code doesn't cause the "sleep" to be bypassed or a
; lot of CPU could be consumed...
; If you have a process which doesn't exit then if it traps, again I'd
; be sure to catch it and add some delay before restarting.
;
; I like the idea of a script at least exiting occassionally to eliminate
; the danger of a memory leak. If you can't do this then I'd monitor memory
; usage over an extended period of time!
;----------------------------------------------------------------------------

;--- Load MAKEMSI (via wrapper) ---------------------------------------------
#include "ME.MMH"

;--- Create INSTALLDIR ------------------------------------------------------
<$DirectoryTree Key="INSTALLDIR" Dir="c:\program files\<$ProdInfo.ProductName>" CHANGE="\" PrimaryFolder="Y">


;----------------------------------------------------------------------------
;--- Install the SERVICE ----------------------------------------------------
;----------------------------------------------------------------------------
#define  SERVICE_NAME              <$ProdInfo.ProductName>
#define  SERVICE_DESC              My VBSCRIPT based service
#define  SERVICE_VBS_BASENAME      MyServiceVbs.VBS
#define  SERVICE_VBS_IN_LOGDIR     <$MAKEMSI_VBSCRIPT_DIR>\<$SERVICE_VBS_BASENAME>
#define  SOURCEDIR_SC.EXE          .\             ;;In current directory
#define  SOURCEDIR_SRVSTART_FILES  srvstart.exe\
<$FileMake "<$SERVICE_VBS_IN_LOGDIR>">
    ;--- Require Variables to be defined and check generated syntax ---------
    option explicit
    <?SyntaxCheck>

    ;--- This service is a bit like a schedule, does some work then pauses ---
    DoStuff()                           ;;Even on trap MUST do pause (below) - could do it first!

    '--- Delays between invokations -------------------------------------------
    wscript.echo "sleeping for 30 minutes..."  ;;Only visible if service "interactive" (good idea to log)
    wscript.sleep 30 * (60 * 1000)             ;;Sleep for 30 minutes
    wscript.quit  0                            ;;srvstart.exe will now restart cscript and this service VBS


    <?NewLine><?NewLine>
    '===========================================================
    sub DoStuff()
    '
    '  This is called roughly every 30 minutes to do some work.
    '===========================================================
        '--- Does something ---
        on error resume next
end sub
<$/FileMake>
#(
    ;--- Simple macro to create component and add file ----------------------
    #define ServiceNeeds
    #evaluate+ ^ItsShortName^ ^FilePart('NAME', '{$Source}')^
    <$Component "VbsServiceNeeds_<$ItsShortName>" Create="Y" Directory_="INSTALLDIR">
       <$File Source="{$Source}" Comment=~{$Comment}~ KeyPath="Y">
    <$/Component>
#)
<$Component "Service" Create="Y" Directory_="INSTALLDIR">
   ;--- Add the service EXE -------------------------------------------------
   <$File KeyPath="Y" Source="<$SOURCEDIR_SRVSTART_FILES>srvstart.exe" Comment='Used to allow VBS to be used as a service (The Windows service manager directly executes this EXE).'>
   <$ServiceNeeds     Source="<$SOURCEDIR_SRVSTART_FILES>srvstart.dll" Comment='Required by "srvstart.exe".'>
   <$ServiceNeeds     Source="<$SOURCEDIR_SRVSTART_FILES>logger.dll"   Comment='Required by "srvstart.exe".'>
   <$ServiceNeeds     Source="<$SOURCEDIR_SC.EXE>sc.exe"               Comment=^This tool is used to set the services recovery options.^>
   <$ServiceNeeds     Source="<$SERVICE_VBS_IN_LOGDIR>"                Comment=^"srvstart.exe" runs this VBS (its the service's code). Its main task is to collects MSI logs into a single directory.^>

   ;--- Set up the "srvstart.ini" file (pick your own options from doco) ----
   <$IniFile "srvstart.ini" DIR="INSTALLDIR">
       <$IniSection "<$SERVICE_NAME>">
           ;--- What what and what current directory ------------------------
           <$Ini "startup"           Value=^"[SystemFolder]cscript.exe" //nologo //T:3600 "<$SERVICE_VBS_BASENAME>" "AnyParameter1" "AnyParameter2Etc"^>
           <$Ini "startup_dir"       Value="[INSTALLDIR]">  ;;Don't quote dir!

           ;--- Set debug level to off/minimal, log to file not NT Event Log ---
           <$Ini "debug"             Value="0">                                         ;;Minimal debug output
           <$Ini "debug_out"         Value="[INSTALLDIR]<$SERVICE_NAME>(Service).LOG">  ;;Log to file (not NT Event Log!)

           ;--- Process priority (not many options..., tools source is available...) ---
           <$Ini "priority"          Value="idle">          ;;Run the task at lowest priority

           ;--- Other options -----------------------------------------------
           <$Ini "auto_restart"      Value="Y">             ;;VBS will stop when finished!
           <$Ini "shutdown_method"   Value="kill">          ;;How to terminate CSCRIPT.EXE
           <$Ini "restart_interval"  Value="2">             ;;Workaround to SVRSTART.EXE (can't stop service) bug (VBS sleeps to cause delay)
       <$/IniSection>
   <$/IniFile>

   ;--- Install the service -------------------------------------------------
   #(
       #define SVRSTART.EXE_PARMS

       ;--- Set debug level to zero to prevent 2 event log messages! --------
       -d 0

       ;--- Set configuration file (created above) --------------------------
       -c "[INSTALLDIR]srvstart.ini"
   #)
   #(
       <$ServiceInstall
             Arguments=^svc <$SERVICE_NAME> <$SVRSTART.EXE_PARMS>^
                  Name="<$SERVICE_NAME>"
           DisplayName="<$SERVICE_NAME>"
           Description="<$SERVICE_DESC>"
               Process="Own"
       >
   #)

   ;--- Control the service (delete on uninstall) ---------------------------
   #(
       <$ServiceControl
                  Name="<$SERVICE_NAME>"
             AtInstall="start stop"
           AtUninstall="stop delete"
       >
   #)

   ;--- Set recovery Options ------------------------------------------------
   #data "CaData_INSTALLDIR"
       "INSTALLDIR" '[INSTALLDIR]'
   #data
   #define RecoveryResetInSeconds 300
   #( '/'
       #define RecoveryActions

       ;--- Note that GUI won't display these correctly (its limited) -------
       restart/60000                ;;1.  Restart after 1  minute
       restart/300000               ;;2.  Restart after 5  minutes
       restart/600000               ;;3+. Restart after 10 minutes
   #)
   <$VbsCa Binary="SetServiceRecovery.vbs" DATA=^CaData_INSTALLDIR^>
       ;--- INSTALL -------------------------------------------------------------
       <$VbsCaEntry "JustBeforeStartServices">
           ;--- Initialization --------------------------------------------------
           dim ScExe   : ScExe   = VbsCaCadGet("INSTALLDIR") & "sc.exe"
           dim ScArgs  : ScArgs  = "failure <$SERVICE_NAME> reset= <$RecoveryResetInSeconds> actions= <$RecoveryActions>"
           dim ScArgsQ : ScArgsQ = "qfailure <$SERVICE_NAME>"

           ;--- Set the recovery information ------------------------------------
           CaDebug 2, "Setting the control services recovery options"
           VbsCaRunSync """" & ScExe & """ " & ScArgs, 0, ""  ;;Ignore RC (can't be trusted)

           ;--- Log the current state of the recovery options -------------------
           CaDebug 2, "Logging the control services recovery options"
           VbsCaRunSync """" & ScExe & """ " & ScArgsQ, 0, ""
       <$/VbsCaEntry>
   <$/VbsCa>
   <$VbsCaSetup Binary="SetServiceRecovery.vbs" Entry="JustBeforeStartServices" Seq="<-StartServices" CONDITION=^<$CONDITION_EXCEPT_UNINSTALL>^ DATA=^CaData_INSTALLDIR^>
<$/Component>


Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.Please email me any feedback, additional information or corrections.
See this page online (look for updates)

[Top][Contents][Prev]: ServiceControl[Next]: Shortcut


MAKEMSI© is (C)opyright Dennis Bareis 2003-2008 (All rights reserved).
Saturday May 28 2022 at 3:11pm
Visit MAKEMSI's Home Page
Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.