#!/usr/bin/perl
use strict;
use warnings;
use lib './lib';
use threads;
use threads::shared;
use constant SERVICE_SLEEP_TIME => 2000; # 20 milliseconds
use File::Spec;
use File::Basename;
use English qw(-no_match_vars);
use Win32;
use Win32::Daemon;
use FusionInventory::Agent;
delete($ENV{PERL5LIB});
delete($ENV{PERLLIB});
my $directory = dirname(File::Spec->rel2abs( __FILE__ ));
# on Win2k, Windows do not chdir to the bin directory
# we need to do it by ourself
chdir($directory);
Win32::Daemon::StartService();
my $thread;
my $state;
my $previousState = SERVICE_START_PENDING;
while (($state = Win32::Daemon::State()) != SERVICE_STOPPED) {
if ($state == SERVICE_START_PENDING) {
# Initialization code
startAgent();
Win32::Daemon::State(SERVICE_RUNNING);
$previousState = SERVICE_RUNNING;
} elsif ($state == SERVICE_STOP_PENDING) {
killAgent();
Win32::Daemon::State(SERVICE_STOPPED);
} elsif ($state == SERVICE_PAUSE_PENDING) {
# "Pausing...";
killAgent();
Win32::Daemon::State(SERVICE_PAUSED);
$previousState = SERVICE_PAUSED;
killAgent();
next;
} elsif ($state == SERVICE_CONTINUE_PENDING) {
# "Resuming...";
startAgent();
Win32::Daemon::State(SERVICE_RUNNING);
$previousState = SERVICE_RUNNING;
next;
} elsif ($state == SERVICE_STOP_PENDING) {
# "Stopping...";
killAgent();
Win32::Daemon::State(SERVICE_STOPPED);
$previousState = SERVICE_STOPPED;
next;
} elsif ($state == SERVICE_RUNNING) {
# The service is running as normal...
# ...add the main code here...
startAgent();
} else {
# Got an unhandled control message. Set the state to
# whatever the previous state was.
Win32::Daemon::State($previousState);
}
# Check for any outstanding commands. Pass in a non zero value
# and it resets the Last Message to SERVICE_CONTROL_NONE.
if (SERVICE_CONTROL_NONE != (my $message = getMessage())) {
if (SERVICE_CONTROL_INTERROGATE == $message) {
# Got here if the Service Control Manager is requesting
# the current state of the service. This can happen for
# a variety of reasons. Report the last state we set.
Win32::Daemon::State($previousState);
} elsif (SERVICE_CONTROL_SHUTDOWN == $message) {
# Yikes! The system is shutting down. We had better clean up
# and stop.
# Tell the SCM that we are preparing to shutdown and that we expect
# it to take 25 seconds, so don't terminate us for at least
# 25 seconds...
Win32::Daemon::State(SERVICE_STOP_PENDING, 25000);
}
}
# Snoose for awhile so we don't suck up cpu time...
Win32::Sleep(SERVICE_SLEEP_TIME);
}
sub getMessage {
if ($Win32::Daemon::VERSION < 20101014) {
return Win32::Daemon::LastControlMessage(1);
} else {
return Win32::Daemon::QueryLastMessage();
}
}
sub startAgent {
return if $thread;
$thread = threads->create(sub {
my $agent = FusionInventory::Agent->new(
confdir => $directory . '/../../etc/fusioninventory',
datadir => $directory . '/../../share',
vardir => $directory . '/../../var',
libdir => $directory . '/../../lib',
);
$agent->init(options => { service => 1 });
$agent->run();
});
}
sub killAgent {
$thread->kill('KILL');
$thread = undef;
}
__END__
=head1 NAME
fusioninventory-win32-service - FusionInventory Agent service for Windows