Introduction
Exsead Service Manager Is An Open Source (BSD Style License) Windows Service Which Launches Anything Via The Use Of Scripts
In the Unix world, the equivalent of services are started using scripts. This makes life very simple indeed. If one wants to add in a background activity, one just adds in a launcher for it into one of these scripts. There is no requirement for a specially complied executable. In the Windows world, we choose to run executables directly off the Windows Service system. These executables must have a special interface compiled into them. Whilst this approach has its merits for many situations, it lacks flexibility and results in poor implementations such as using level 'Run' registry directives where services would be much more preferable.
The aim of Exsead Service Manager is to fit in as part of the entire Exsead concept: EXtreme Script Enterprise Application Development. In this case, the specific aim is to launch scripts as services. Once a service is scripted, you can do anything, easily!
Please help! ExseadServiceManager is now a Source Forge project. I am actively developing, but need help setting up the Source Forge SSH, CVS and Website.
If anyone is interested in helping with the project, please feel free to contact me at ajt(at)nerds-central.com. For now, the current release and source code can be found here. As I develop the product, I shall be placing new releases there. Keep an eye on Nerds-Central for news. The current version is in constant use by myself and I consider the core features to be beta for XP/SP2. Some of the features and for other operating systems, I would consider it to be alpha.
How Does ExseadServiceManager Actually Work?
The service manager itself is just a single executable. This executable installs, configures, uninstalls and runs the service. It differentiates which one is required of it by the way it is run and the nature of the command line arguments.
The steps to installing and using the service manager are as follows:
Naming the Service
Everything about ExseadServiceManager
has been designed to be simple. I mean, a lot of thought was put into making using this application simple. Here is the first example. The name of the service it manages is controlled by the name of the executable. If you want to create a service called 'FlyingPigsNeedNappies
' (diapers) then you make a copy of ExseadServiceManager.exe and rename it FlyingPigsNeedNappies.exe. It is that simple – really.
Where will it run?
When you install the service using the ExseadServiceManager
, it sets the working directory of the service to the directory from which the installation was done. So, if you make a directory c:\FlyingPigs\Service and open a CMD box, change directory to c:\FlyingPigs\Service and run FlyingPigsNeedNappies.exe -I
, then the service will run in c:\FlyingPigs\Service. Again – simple.
Install the Service
As it says above, you just run the executable with the -I
option. This will make it run as local admin. If you use the -i
option, then it will run as a different account.
Configuring the Service
The service can be configured, started, stopped and uninstalled from the command line options of the executable.
Connecting the Service to something
It is all very well setting up this service, but it has to do something. This is achieved by the script which has the same name as the executable but with the file extension vbs. For this version, only VBScript is supported for the initial script, but that should be addressed in later versions. So, in the flying pigs example, the initial script will have the name FlyingPigsNeedNappies.vbs. I'll discuss the structure of the initial script later in this post.
Where does the logging go?
The log for the service manager when running as a service goes to the default temp directory of the account that it is running as. For example, if it is running as Local Admin, then it will send the log to name.log in Windows\Temp. For the flying pigs example, it would be Windows\FlyingPigsNeedNappies.log. Please note that the amount of information sent to the log is small because the majority of the work in running the service is done by the initial script, not the service manager. Here is an example log output:
Service Main Called
Service Handler Acquired
Opening Service: 'TAGService'
Changing working dir to 'C:\CodeRepo\InfraStructure\InstallationAids'
About to run 'start'
Acquiring script object: TAGService.vbs
Acquired script object.
Loaded Script OK.
Here is the full list of command line options for the executable as written by running it with the -?
option:
Exsead Service Manager: Command Line Args
-? Print this message
-r run start method directly avoiding service
-e print out current env block
-i 'user' 'pass' install service
-I install service as local admin
-u uninstall service
-v print version info
-s start service
-k stop service
-K first kill all descendants of the service process then stop service
-Z first kill all descendants of the process then kill it.
-M set to manual start
-A set to auto start
-D set to disabled
-S set to system start
-B set to boot start
Notes: -K suspends the processes as it traverses the tree, but even with this
level of checking, it might not get them all or it might kill a process
that has just received the same pid as one that used to be a descendent.
Please use this function with caution. This also applies to -Z.
Creating And Initial Service Script
At a minimum, the initial script must have two subroutines in it: StartService
and StopService
. Neither of these take any arguments.
StartService
is called by the service manager when the service itself is started. This subroutine must initiate whatever the service does. When this subroutine exits, the service will stop. This means that if you want the service to stay running, you must not let this subroutine until the service is forced to stop. This can be done by an infinite loop, see the example below.
StopService
is called by the service manager when the service is asked to stop by Windows. This can be initiated by running the executable with the -k
option or using some other utility. StopService
is called in a different thread of activity to start service, so it does not matter that StartService
has not exited. In StopService
, you must do whatever process shutdown and cleanup is required return.
Here is a real world initialize script which runs the TAGService
for the TAG web application gateway:
Option Explicit
CONST SERVICE_NAME = "TAGService"
CONST ForReading = 1, ForWriting = 2, ForAppending = 3
Dim objWSHShell
Dim objWSHNetwork
Dim objFSO
Dim objLogger
Dim is_init
sub init()
if not is_init then
Set objWSHShell = CreateObject("WScript.Shell")
Set objWSHNetwork = CreateObject("WScript.Network")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objLogger = new Logger
is_init=true
end if
end sub
class Logger
private logFile
Private Sub Class_Initialize()
set logFile=objFSO.openTextFile(SERVICE_NAME+"_script.log",ForWriting,true)
End Sub
public sub WriteLog(what)
logFile.writeLine(what)
end sub
Private Sub Class_Terminate()
logFile.close
End Sub
end class
sub StartService()
init
Dim curdir
dim tagFile
curdir = objWSHShell.CurrentDirectory
tagFile = curdir & "\..\CRI\bin\TAG_Runner.exe"
If not objFSO.FileExists(tagFile) then
SilentReport "Could not find " & tagFile, 0
exit sub
end if
objWSHShell.CurrentDirectory=curdir +"\..\CRI\bin"
while 1=1
objWSHShell.run "TAG_Runner.exe",0,true
wend
end sub
sub StopService()
init
objWSHShell.run SERVICE_NAME + ".exe -K"
end sub
Sub SilentReport(sString, iErr)
init
objLogger.WriteLog(now & ": " & sString & " , " & iErr)
End Sub
For more on this and other topics, please see Nerds-Central.