The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Win32::Daemon::Simple - framework for Windows services

SYNOPSIS

        use FindBin qw($Bin $Script);
        use File::Spec;
        use Win32::Daemon::Simple
                Service => 'SERVICENAME',
                Name => 'SERVICE NAME',
                Version => 'x.x',
                Info => {
                        display =>  'SERVICEDISPLAYNAME',
                        description => 'SERVICEDESCRIPTION',
                        user    =>  '',
                        pwd     =>  '',
                        interactive => 0,
        #               path    =>  $^X,
        #               parameters => "$Bin\\$Script",
                },
                Params => {
                        Tick => 0,
                        Talkative => 0,
                        Interval => 10, # minutes
                        LogFile => "$Bin\\Import",
                        # ...
                        Description => <<'*END*',
        Tick : (0/1) controls whether the service writes a "tick" message to
          the log once a minute if there's nothing to do
        Talkative : controls the amount of logging information
        Interval : how often does the service look for new or modified files
          (in minutes)
        LogFile : the path to the log file
        ...
        *END*
                },
                param_modify => {
                        LogFile => sub {File::Spec->rel2abs($_[0])},
                        Interval => sub {no warnings;my $interval = 0+$_[0]; die "The interval must be a positive number!\n" unless $interval > 0;return $interval},
                        Tick => sub {return ($_[0] ? 1 : 0)},
                };

        # initialization

        ServiceLoop(\&doTheJob);

        # cleanup

        Log("Going down");
        exit;

        # definition of doTheJob()
        # You may want to call DoEvents() within the doTheJob() at places where it
        # would be safe to pause or stop the service if the processing takes a lot of time.
        # Eg. DoEvents( \&close_db, \&open_db, sub {close_db(); cleanup();1})

DESCRIPTION

This module will take care of the instalation/deinstalation, reading, storing and modifying parameters, service loop with status processing and logging. It's a simple to use framework for services that need to wake up from time to time and do its job and otherwise should just poll the service status and sleep as well as services that watch something and poll the Service Manager requests from time to time.

You may leave the looping to the module and only write a procedure that will be called in the specified intervals or loop yourself and allow the module to process the requests when it fits you.

This module should allow you to create your services in a simple and consistent way. You just provide the service name and other settings and the actuall processing, the service related stuff and commandline parameters are taken care off already.

EXPORT

ServiceLoop

        ServiceLoop( \&processing)

Starts the event processing loop. The subroutine you pass will be called in the specified intervals.

In the loop the module tests the service status and processes requests from Service Manager, ticks (writes "Tick at $TimeStamp" messages once a minute if the Tick parameter is set) and calls your callback if the interval is out. Then it will sleep(1).

DoEvents

        DoEvents()
        DoEvents( $PauseProc, $UnPauseProc, $StopProc)

You may call this procedure at any time to process the requests from the Service Manager. The first parameter specifies what is to be done if the service is to be paused, the second when it has to continue and the third when it's asked to stop.

If $PauseProc is:

        undef : the service is automaticaly paused,
                DoEvents() returns after the Service Manager asks it to continue
        not a code ref and true : the service is automaticaly paused,
                DoEvents() returns after the Service Manager asks it to continue
        not a code ref and false : the service is not paused,
                DoEvents() returns SERVICE_PAUSE_PENDING immediately.
        a code reference : the procedure is executed. If it returns true
                the service is paused and DoEvents() returns after the service
                manager asks the service to continue, if it returns false DoEvents()
                returns SERVICE_PAUSE_PENDING.

If $UnpauseProc is:

        a code reference : the procedure will be executed when the service returns from
                the paused state.
        anything else : nothing will be done

If $StopProc is:

        undef : the service is automaticaly stopped and
                the process exits
        not a code ref and true : the service is automaticaly stopped and
                the process exits
        not a code ref and false : the service is not stopped,
                DoEvents() returns SERVICE_STOP_PENDING immediately.
        a code reference : the procedure is executed. If it returns true
                the service is stopped and the process exits, if it returns false DoEvents()
                returns SERVICE_PAUSE_PENDING.

Pause

        Pause()
        Pause($UnPauseProc, $StopProc)

If the DoEvents() returned SERVICE_STOP_PENDING you should do whatever you need to get the service to a pausable state (close open database connections etc.) and call this procedure. The meanings of the parameters is the same as for DoEvents().

Log

Writes the parameters to the log file (and in commandline mode also to the console). Appends " at $TimeStamp\n" to the message.

LogNT

Writes the parameters to the log file (and in command line mode also to the console). Only appends the newline.

ReadParam

        $value = ReadParam( $paramname, $default);

Reads the value of a parameter stored in HKLM\SYSTEM\CurrentControlSet\Services\SERVICENAME\Parameters If there is no value with that name returns the $default.

SaveParam

        SaveParam( $paramname, $value);

Stores the new value of the parameter in HKLM\SYSTEM\CurrentControlSet\Services\SERVICENAME\Parameters.

CatchMessages

        CatchMessages( $boolean);

Turns on or off capturing of messages passed to Log() or LogNT(). Clears the buffer.

GetMessages

        $messages = GetMessages();

Returns the messages captured since CatchMessages(1) or last GetMessages(). Clears the buffer.

These two functions are handy if you want to mail the result of a task. You just CatchMessages(1) when you start the task and GetMessages() and CatchMessages(0) when you are done.

CMDLINE

Constant. If set to 1 the service is running in the command line mode, otherwise set to 0.

PARAMETERNAME

For each parameter specified in the params={...}> option the module reads the actual value from the registry (using the value from the params={...}> option as a default) and defines a constant named uc($parametername).

Service parameters

The service created using this module will accept the following commandline parameters:

-install

Installs the service and stores the default values of the parameters to the registry into HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName\Parameters

If you get an error like

        Failed to install: The specified service has been marked for deletion.

or

        Failed to install: The specified service already exists.

close the Services window and/or the regedit and try again!

-uninstall

Uninstalls the service.

-params

Prints the actual values of all the parameters of the service.

-help

Prints the name and version of the service and the list of options. If the parameters=>{} option contained a Description, then the Description is printed as well.

-default

Sets all parameters to their default values.

-PARAM

Sets the value of PARAM to 1. The parameter names are case insensitive.

-noPARAM

Sets the value of PARAM to 1. The parameter names are case insensitive.

-PARAM=value

Sets the value of PARAM to value. The parameter names are case insensitive.

You may validate and/or modify the value with a handler specified in the param_modify=>{} option. If the handler die()s the value will NOT be changed and the error message will be printed to the screen.

-defaultPARAM

Deletes the parameter from registry, therefore the default value of that parameter will be used each time the service starts.

Comments

The scripts using this module are sensitive to the way they were started.

If you start them with a parameter they process that parameter as explained abovet. Then if you started them from the Run dialog or by doubleclicking they print (press ENTER to continue) and wait for the user to press enter, if you started them from the command prompt they exit immediately

If they are started without parameters by the Service Manager they register with the Manager and start your code, if they are started without parameters from command prompt they start working in a command line mode (all info is printed to the screen as well as to the log file) and if they are started by doubleclicking on the script they show the -help screen.

AUTHOR

 Jenda@Krynicky.cz
 http://Jenda.Krynicky.cz

SEE ALSO

Win32::Daemon.