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]: SMOKE.EXE[Next]: STRFINFO.EXE
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
\->Tips and Tricks->Tools->SRVSTART.EXE

SRVSTART.EXE

This is a free tool which wraps VBSCRIPT or any other command line in such a way that it can be used as a service. To get more details or to download the latest copy visit "http://www.nick.rozanski.org.uk/index.php?page=software".

The source code is also available so you could fix any of the bugs or features listed here, if so I'm sure lots of people would appreciate you making these available (or passing them back to the author)...

Note that I do not recommend the MS tool "SRVANY.EXE" as it does not handle the wrapped process terminating (that is, "its garbage").

SRVSTART.EXE TIPS

  1. There is a bug in this tool that I reported to the author and that is while in a "restart_interval" the service can't be stopped, for this reason this must be very small. So for example if you wish 30 minute gaps in your processing put an appropriate sleep in your script and keep the restart_interval small (such as 2 seconds).

  2. Do not have a service start a batch file or command processor which then starts a long running script (or other similar scenario) as this program kills the command processor but not the script. I suspect it kills the child process but not the process tree. This could cause uninstall (or install) or service stop (or restart) issues.

    One example of a no-no is to attempt to overcome the limitations on the available priority options with a command similar to "start /wait /b /BelowNormal" ...". It would be wise to use Task Manager or better yet "Process Explorer" to watch service starting and stopping to ensure any child process you might launch end at service shutdown.

  3. Debug messages go into the event log by default, you can direct these to a file instead. Event log messages will be displayed along with the standard "The description for Event ID ( 0 ) in Source ( SRVSTART ) cannot be found" as the tool does not register the "source". Redirect the output as early as possible on the command line or INI so and to also capture any command line or INI issues...

  4. If the command being executed returns a non-zero value then log messages are generated. If the return code is meaningless then its best to ensure its 0!

SRVSTART.EXE -?

The following only gives you an idea of the options available and there is a separate INI configuration possible (see the products web site for more details).

SRVSTART version 1.10
Copyright (C) 1998 - 2000 Nick Rozanski (Nick@Rozanski.com)

Start a program with a given environment, and optionally as a NT service
 or install / remove an NT service which uses SRVSTART

Syntax for command mode:
 srvstart cmd window_title [options] command [program_parameters...]

Syntax for service mode:
 srvstart [ svc ] service_name [options] command [program_parameters...]

Syntax for any mode (try service, then command):
 srvstart any service_name [options] command [program_parameters...]

Syntax for install mode:
 srvstart install|install_desktop service_name -c controlfile

Syntax for remove mode:
 srvstart remove service_name

service_name is short (internal) name of NT service

options:

  -e var=value assign value to environment variable var
  -p path      assign value of %PATH%
  -l libdir    assign value of %LIB%
  -s sybase    assign value of %SYBASE% variable
  -q sybase    assign default %PATH% based on this value of %SYBASE%

  -x priority  run at given execution priority (normal/high/real/idle)
  -w           start in new window (command mode only)
  -m           start in minimised new window (command mode only)
  -y sec       delay sec seconds before reporting 'started' (service mode only)
  -t sec       program status check interval (service mode only)

  -d level     debug level (0/1/2, 2 highest)
  -o target    send debug output to target (filename or - for stdout or LOG for NT Event Log)
  -c ctrlfile  get srvstart options from file ctrlfile
  -h           display this help message

Substitute parameters in command using {prompt} or {prompt:default}
Substitute environment vars in command using %variable%
Refer to exe.cpp for details.

Distributed under the terms of the GNU General Public License as published by the Free Software Foundation

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]: SMOKE.EXE[Next]: STRFINFO.EXE


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.