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 |
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.
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>