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

NAME

Win32::Daemon - Extension enabling Win32 Perl scripts to be a service

SYNOPSIS

        use Win32::Daemon;
    Win32::Daemon::StartService();
        I<...process Perl code...>
    Win32::Daemon::StopService();

DESCRIPTION

This extension enables a Win32 Perl script to act as a true Win32 service.

FUNCTIONS

    CreateService()
    DeleteService() 
    GetLastError()
    GetServiceHandle()
    HideService()
    QueryLastMessage()
    RestoreService()
    SetServiceBits()
    ShowService()
    StartService()
    State()
    StopService()   
    Timeout()
    
StartService()

This starts a new service thread. The script should call this as soon as possible. When the service manager starts the service Perl is started and the script is loaded.

StopService()

This will instruct the service to terminate.

QueryLastMessage()

This function returns the last message that the service manager has sent to the service.

Occasionally the service manager will send messages to the service. These messages typically request the service to change from one state to another. It is important that the Perl script responds to each message otherwise the service manager becomes confused about the current state of the service. For example, if the service manager is submits a SERVICE_PAUSE_PENDING then it expects the Perl script to recognize the change to a paused state and submit the new state by calling State( SERVICE_PAUSED ).

You can update the service manager with the current status using the State() function.

Possible values returned are:

    SERVICE_STOPPED............The service is stopped
    SERVICE_RUNNING............The service is running
    SERVICE_PAUSED.............The service is paused
    SERVICE_START_PENDING......The service manager is attempting to start the service
    SERVICE_STOP_PENDING.......The service manager is attempting to stop the service
    SERVICE_CONTINUE_PENDING...The service manager is attempting to resume the service
    SERVICE_PAUSE_PENDING......The service manager is attempting to pause the service
    SERVICE_INTERROGATE........The service manager is querying the service's state

    Windows 2000 specific messages:
    SERVICE_CONTROL_SHUTDOWN..........The machine is shutting down. This indicates that
                                      the service has roughly 20 seconds to clean up
                                      and terminate. This time can be extended by
                                      submitting SERVICE_STOP_PENDING via the State() function.
    SERVICE_CONTROL_PARAMCHANGE.......Service parameters have been modified.
    SERVICE_CONTROL_NETBINDADD........A network binding as been added.
    SERVICE_CONTROL_NETBINDREMOVE.....A network binding has been removed.
    SERVICE_CONTROL_NETBINDENABLE.....A network binding has been enabled.
    SERVICE_CONTROL_NETBINDDISABLE....A network binding has been disabled.

    SERVICE_CONTROL_USER_DEFINED......This is a user defined control. There are 127 of these
                                      beginning with SERVICE_CONTROL_USER_DEFINED as the base.

Note: When the system shuts down it will send a SERVICE_CONTROL_SHUTDOWN message. The Perl script has approximately 20 seconds to perform any shutdown activities before the Control Manger stops the service. If more time is needed call the State() function passing in the SERVICE_STOP_PENDING control message along with how many seconds it will take to shutdown the service. This time value is only an estimate. When the service is finally ready to stop it must submit the SERVICE_STOPPED message as in:

    if( SERVICE_CONTROL_SHUTDOWN == State() )
    {
        Win32::Daemon::State( SERVICE_STOP_PENDING, 30 );
        I<...process code...>
        Win32::Daemon::State( SERVICE_STOPPED );
    }
State([$NewState])

This function returns the current state of the service. It can optionally update the status of the service as well. This is the last status reported to the service manager.

Optionally you can pass in a value that will be sent to the service manager.

Possible values returned (or submitted):

    SERVICE_STOPPED............The service is stopped
    SERVICE_RUNNING............The service is running
    SERVICE_PAUSED.............The service is paused
    SERVICE_START_PENDING......The service manager is attempting to start the service
    SERVICE_STOP_PENDING.......The service manager is attempting to stop the service
    SERVICE_CONTINUE_PENDING...The service manager is attempting to resume the service
    SERVICE_PAUSE_PENDING......The service manager is attempting to pause the service

Example: Simple Service

This example service will delete all .tmp files from the c:\temp directory every time it starts. It will immediately terminate.

        use Win32::Daemon;

    # Tell the OS to start processing the service...
    Win32::Daemon::StartService();

    # Wait until the service manager is ready for us to continue...
    while( SERVICE_START_PENDING != Win32::Daemon::State() )
    {
        sleep( 1 );
    }

    # Now let the service manager know that we are running...
    Win32::Daemon::State( SERVICE_RUNNING );

    # Okay, go ahead and process stuff...
    unlink( glob( "c:\\temp\\*.tmp" ) );

    # Tell the OS that the service is terminating...
    Win32::Daemon::StopService();

This particular example does not really illustrate the capabilities of a Perl based service.

Example: Monitoring a directory

Example: Install the service

Assuming that Perl.exe is in c:\perl\bin and the service script is c:\perl\scripts\service.pl then this script will install the script as a service. Since no user is specified it defaults to the LocalSystem.

    use Win32::Daemon; 
    %Hash = (
        name    =>  'PerlTest',
        display =>  'Oh my GOD, Perl is a service!',
        path    =>  'c:\perl\bin\perl.exe',
        user    =>  '',
        pwd     =>  '',
        parameters =>'c:\perl\scripts\service.pl',
    );
    if( Win32::Daemon::CreateService( \%Hash ) )
    {
        print "Successfully added.\n";
    }
    else
    {
        print "Failed to add service: " . Win32::FormatMessage( Win32::Daemon::GetLastError() ) . "\n";
    }

NOTES: - ConfigureService: - If you specify a 'parameters' key you MUST specify a 'path' key.