#!/usr/bin/perl $| = 1; use strict; use Getopt::Long; use Win32; use Win32::Daemon; my %opt; GetOptions ( \%opt, "run", "install", "remove", "start", "stop", "restart", "pause", "resume|continue", ); my @currDir = split /\//, $0; my $script = $0; my $scriptPath = "."; if (scalar @currDir > 1) { $script = pop @currDir; $scriptPath = join "/", @currDir; chdir( $scriptPath ); } my %serviceConfig = ( name => 'mytest', display => 'mytest', description => 'this is my test description', machine => '', path => $^X, parameters => ( sprintf '"e:/dia/temp/service.pl" --run', $scriptPath, $script ), start_type => SERVICE_AUTO_START, ); Win32::Daemon::RegisterCallbacks( { start => \&startService, stop => \&stopService, pause => \&pauseService, continue => \&continueService, running => \&runService, } ); # ============================================================================== # main # ============================================================================== if( $opt { install } ) { &installService(); exit(); } elsif( $opt { remove } ) { &removeService(); exit(); } elsif( $opt { status } ) { &serviceStatus(); exit(); } elsif( $opt { run } ) { my %context = { last_state => SERVICE_STOPPED, count => 0, start_time => time(), }; Win32::Daemon::StartService( \%context, 5000 ); } elsif( $opt { start } ) { my $cmd = sprintf 'net start %s', $serviceConfig { name }; system( $cmd ); exit(); } elsif( $opt { stop } ) { my $cmd = sprintf 'net stop %s', $serviceConfig { name }; system( $cmd ); exit(); } elsif( $opt { pause } ) { my $cmd = sprintf 'net pause %s', $serviceConfig { name }; system( $cmd ); exit(); } elsif( $opt { resume } ) { my $cmd = sprintf 'net continue %s', $serviceConfig { name }; system( $cmd ); exit(); } elsif( $opt { restart } ) { my $cmd = sprintf 'net stop %s', $serviceConfig { name }; system( $cmd ); $cmd = sprintf 'net start %s', $serviceConfig { name }; system( $cmd ); exit(); } else { die "Nothing to do\n"; } # ============================================================================== # SERVICE SETUP # ============================================================================== sub installService { # installs the win32 service daemon # --------------------------------- if( Win32::Daemon::CreateService( \%serviceConfig ) ) { &debug( 'The service [%s] was successfully installed', $serviceConfig { display } ); } else { &debug( 'Failed to install the service [%s]: %s', $serviceConfig { display }, GetError() ); } } # ============================================================================== sub removeService { # removes the win32 service daemon # -------------------------------- if( Win32::Daemon::DeleteService( $serviceConfig { name } ) ) { &debug( 'The service [%s] was successfully removed', $serviceConfig { display } ); } else { &debug( 'Failed to remove the service [%s]: %s', $serviceConfig { display }, GetError() ); } } # ============================================================================== # CALLBACK ROUTINES # ============================================================================== sub startService { # start the win32 service daemon # ------------------------------ my ($event, $context) = @_; $context -> { last_state } = SERVICE_RUNNING; Win32::Daemon::State( SERVICE_START_PENDING, 30000 ); &debug( 'Starting the service' ); # let's go Win32::Daemon::State( SERVICE_RUNNING ); } # ============================================================================== sub stopService { # stop the win32 service daemon # ----------------------------- my ($event, $context) = @_; $context -> { last_state } = SERVICE_STOPPED; Win32::Daemon::State( SERVICE_STOP_PENDING, 30000 ); &debug( 'Stopping the service' ); Win32::Daemon::State( SERVICE_STOPPED ); Win32::Daemon::StopService(); } # ============================================================================== sub pauseService { # let the win32 service daemon make a pause # ----------------------------------------- my ($event, $context) = @_; &debug( 'Pausing the service' ); $context -> { last_state } = SERVICE_PAUSED; Win32::Daemon::State( SERVICE_PAUSED ); } # ============================================================================== sub continueService { # let the win32 service daemon exit a pause # ----------------------------------------- my ($event, $context) = @_; &debug( 'Resuming the service' ); $context -> { last_state } = SERVICE_RUNNING; Win32::Daemon::State( SERVICE_RUNNING ); } # ============================================================================== sub runService { # this is the callback of by the win32 service daemon # --------------------------------------------------- my ($event, $context) = @_; if ( Win32::Daemon::State() == SERVICE_RUNNING ) { # count the number of calls (I do not know why) $context -> { count }++; } } sub debug { my ($fmt, @data) = @_; my $message = sprintf $fmt, @data; open( FILE, ">>e:/dia/temp/service.log" ); print FILE "$message\n"; close( FILE ); if (-t STDOUT && -t STDIN) { print "$message\n"; } } # ============================================================================== sub GetError { # returns win32 daemon errors # --------------------------- return( Win32::FormatMessage( Win32::Daemon::GetLastError() ) ); } # ============================================================================== __END__