use constant SERVICE_CONTROL_STOP => 0x00000001;
use constant SERVICE_CONTROL_PAUSE => 0x00000002;
use constant SERVICE_CONTROL_CONTINUE => 0x00000003;
use constant SERVICE_CONTROL_INTERROGATE=> 0x00000004;
use constant SERVICE_CONTROL_SHUTDOWN => 0x00000005;
use constant SERVICE_CONTROL_PARAMCHANGE=> 0x00000006;
use constant SERVICE_CONTROL_NETBINDADD => 0x00000007;
use constant SERVICE_CONTROL_NETBINDREMOVE => 0x00000008;
use constant SERVICE_CONTROL_NETBINDENABLE => 0x00000009;
use constant SERVICE_CONTROL_NETBINDDISABLE=> 0x0000000A;
use constant SERVICE_CONTROL_DEVICEEVENT=> 0x0000000B;
use constant SERVICE_CONTROL_HARDWAREPROFILECHANGE => 0x0000000C;
use constant SERVICE_CONTROL_POWEREVENT => 0x0000000D;
use constant SERVICE_CONTROL_SESSIONCHANGE=> 0x0000000E;
use constant SERVICE_CONTROL_PRESHUTDOWN => 0x0000000F;
# Next 2 are not supported in Win2k and XP
use constant SERVICE_CONTROL_TIMECHANGE => 0x00000010;
use constant SERVICE_CONTROL_TGIGGEREVENT => 0x00000020;
use constant SERVICE_STOPPED => 0x00000001;
use constant SERVICE_START_PENDING => 0x00000002;
use constant SERVICE_STOP_PENDING => 0x00000003;
use constant SERVICE_RUNNING => 0x00000004;
use constant SERVICE_CONTINUE_PENDING => 0x00000005;
use constant SERVICE_PAUSE_PENDING => 0x00000006;
use constant SERVICE_PAUSED => 0x00000007;
####
Win32::Daemon::AcceptedControls(
&SERVICE_CONTROL_STOP| &SERVICE_CONTROL_PAUSE|
&SERVICE_CONTROL_CONTINUE| SERVICE_CONTROL_INTERROGATE| &SERVICE_CONTROL_SHUTDOWN| &SERVICE_CONTROL_PARAMCHANGE|
&SERVICE_CONTROL_NETBINDADD|&SERVICE_CONTROL_NETBINDREMOVE| &SERVICE_CONTROL_NETBINDENABLE| &SERVICE_CONTROL_NETBINDDISABLE|
&SERVICE_CONTROL_DEVICEEVENT| &SERVICE_CONTROL_HARDWAREPROFILECHANGE |
&SERVICE_CONTROL_POWEREVENT|&SERVICE_CONTROL_SESSIONCHANGE|
&SERVICE_CONTROL_PRESHUTDOWN|&SERVICE_CONTROL_TIMECHANGE|
&SERVICE_CONTROL_TGIGGEREVENT );
####
use Win32::Daemon;
use constant SERVICE_CONTROL_STOP => 0x00000001;
use constant SERVICE_CONTROL_PAUSE => 0x00000002;
use constant SERVICE_CONTROL_CONTINUE => 0x00000003;
use constant SERVICE_CONTROL_INTERROGATE => 0x00000004;
use constant SERVICE_CONTROL_SHUTDOWN => 0x00000005;
use constant SERVICE_CONTROL_PARAMCHANGE => 0x00000006;
use constant SERVICE_CONTROL_NETBINDADD => 0x00000007;
use constant SERVICE_CONTROL_NETBINDREMOVE => 0x00000008;
use constant SERVICE_CONTROL_NETBINDENABLE => 0x00000009;
use constant SERVICE_CONTROL_NETBINDDISABLE => 0x0000000A;
use constant SERVICE_CONTROL_DEVICEEVENT => 0x0000000B;
use constant SERVICE_CONTROL_HARDWAREPROFILECHANGE => 0x0000000C;
use constant SERVICE_CONTROL_POWEREVENT => 0x0000000D;
use constant SERVICE_CONTROL_SESSIONCHANGE => 0x0000000E;
use constant SERVICE_CONTROL_PRESHUTDOWN => 0x0000000F;
use constant SERVICE_CONTROL_TIMECHANGE => 0x00000010; # XP & Vista: Not Supported
use constant SERVICE_CONTROL_TGIGGEREVENT => 0x00000020; # XP & Vista: Not Supported
use constant SERVICE_STOPPED => 0x00000001;
use constant SERVICE_START_PENDING => 0x00000002;
use constant SERVICE_STOP_PENDING => 0x00000003;
use constant SERVICE_RUNNING => 0x00000004;
use constant SERVICE_CONTINUE_PENDING => 0x00000005;
use constant SERVICE_PAUSE_PENDING => 0x00000006;
use constant SERVICE_PAUSED => 0x00000007;
my %List;
my $START_TIME = time();
my $DEFAULT_CALLBACK_TIMER = 5000;
my ( $SCRIPT_DIR, $SCRIPT_FILE_NAME ) = ( Win32::GetFullPathName( $0 ) =~ /^(.*)\\([^\\]*)$/ );
$| = 1;
my $LOG_FILE = 'C:\RothExample.log';
if( open( LOG, ">$LOG_FILE" ) ){
my $StartTime = localtime( $START_TIME );
my $BackupHandle = select( LOG );
$| = 1;
select( $BackupHandle );
}
Win32::Daemon::RegisterCallbacks( \&CallbackRoutine );
Log( "Starting service" );
my %Context = (
last_state => SERVICE_STOPPED,
count => 0,
start_time => time(),
);
Win32::Daemon::AcceptedControls(&SERVICE_CONTROL_STOP |
&SERVICE_CONTROL_PAUSE |
&SERVICE_CONTROL_CONTINUE |
&SERVICE_CONTROL_INTERROGATE|
&SERVICE_CONTROL_SHUTDOWN |
&SERVICE_CONTROL_PARAMCHANGE|
&SERVICE_CONTROL_NETBINDADD |
&SERVICE_CONTROL_NETBINDREMOVE |
&SERVICE_CONTROL_NETBINDENABLE |
&SERVICE_CONTROL_NETBINDDISABLE|
&SERVICE_CONTROL_DEVICEEVENT |
&SERVICE_CONTROL_HARDWAREPROFILECHANGE |
&SERVICE_CONTROL_POWEREVENT |
&SERVICE_CONTROL_SESSIONCHANGE |
&SERVICE_CONTROL_PRESHUTDOWN |
&SERVICE_CONTROL_TIMECHANGE |
&SERVICE_CONTROL_TGIGGEREVENT );
Win32::Daemon::StartService( \%Context, $DEFAULT_CALLBACK_TIMER );
Log( "."x60 );
Log( "Shutting down the service." );
Log( "Start time: " . localtime( $Context{start_time} ) );
Log( "End time: " . localtime() );
Log( "Total running callback count: $Context{count}\n" );
#
# Define the callback routine
#
sub CallbackRoutine {
my( $Event, $Context ) = @_;
my $Event_debug = Win32::Daemon::QueryLastMessage();
Win32::Daemon::QueryLastMessage(1); # Reset the Event
my $State = Win32::Daemon::State();
Log( "---------- Entering Loop with Status/Event: $State/$Event ($Event_debug)" );
# Evaluate STATE
if( SERVICE_RUNNING == $State ) {
$Context->{count}++;
Log( "Running!!! Count=$Context->{count}. Timer:".Win32::Daemon::CallbackTimer() );
} elsif( SERVICE_START_PENDING == $State ) {
# Initialization code
$Context->{last_state} = SERVICE_RUNNING;
Win32::Daemon::State( SERVICE_RUNNING );
Log( "Service initialized. Setting state to Running." );
} elsif( SERVICE_PAUSE_PENDING == $State ) {
$Context->{last_state} = SERVICE_PAUSED;
Win32::Daemon::State( SERVICE_PAUSED );
Win32::Daemon::CallbackTimer( 0 );
Log( "Pausing." );
} elsif( SERVICE_CONTINUE_PENDING == $State ) {
$Context->{last_state} = SERVICE_RUNNING;
Win32::Daemon::State( SERVICE_RUNNING );
Win32::Daemon::CallbackTimer( $DEFAULT_CALLBACK_TIMER );
Log( "Resuming from paused state." );
} else {
Log( "Service got an unknown STATE: $State" );
}
# Evaluate CONTROLS / Events
if( SERVICE_CONTROL_STOP == $Event ) {
$Context->{last_state} = SERVICE_STOPPED; # eigentlich STOP_PENDING ???
Win32::Daemon::State( [ state => SERVICE_STOPPED, error => 1234 ] );
Log( "Stopping service." );
# We need to notify the Daemon that we want to stop callbacks and the service.
Win32::Daemon::StopService();
} elsif( SERVICE_CONTROL_SHUTDOWN == $Event ) {
Log( "Event: SHUTTING DOWN! *** Stopping this service ***" );
# We need to notify the Daemon that we want to stop callbacks and the service.
Win32::Daemon::StopService();
} elsif( SERVICE_CONTROL_PRESHUTDOWN == $Event ) {
Log( "Event: Preshutdown!" );
} elsif( SERVICE_CONTROL_INTERROGATE == $Event ) {
Log( "Event: Interrogation!" );
} elsif( SERVICE_CONTROL_NETBINDADD == $Event ) {
Log( "Event: Adding a network binding!" );
} elsif( SERVICE_CONTROL_NETBINDREMOVE == $Event ) {
Log( "Event: Removing a network binding!" );
} elsif( SERVICE_CONTROL_NETBINDENABLE == $Event ) {
Log( "Event: Network binding has been enabled!" );
} elsif( SERVICE_CONTROL_NETBINDDISABLE == $Event ) {
Log( "Event: Network binding has been disabled!" );
} elsif( SERVICE_CONTROL_DEVICEEVENT == $Event ) {
Log( "Event: A device has issued some event of some sort!" );
} elsif( SERVICE_CONTROL_HARDWAREPROFILECHANGE == $Event ) {
Log( "Event: Hardware profile has changed!" );
} elsif( SERVICE_CONTROL_POWEREVENT == $Event ) {
Log( "Event: Some power event has occured!" );
} elsif( SERVICE_CONTROL_SESSIONCHANGE == $Event ) {
Log( "Event: User session has changed!" );
} else {
# Take care of unhandled states by setting the State()
# to whatever the last state was we set...
Win32::Daemon::State( $Context->{last_state} );
Log( "Got an unknown EVENT: $Event" );
}
return();
}
sub Log{
my( $Message ) = @_;
if( fileno( LOG ) ){
print LOG "[" . localtime() . "] $Message\n";
}
}