Search code examples
windowsperl

Perl script to start/stop windows service


Here is the script for checking status of windows services and if they are in stop state, it will start the service. I can able to get the status of service, but can't able to start services. please help and let me know what I need to do.

#!/usr/local/bin/perl

use Win32::Service;
use strict;

sub checkService();
sub getDate();
sub getTime();
sub logEvent();

my @timeInfo = localtime(time);
my $serviceName = "TapiSrv";
my $currentDate = getDate();
my $currentTime = getTime();
my %status;
my %status_code = (1 => 'not running',
               2 => 'start pending',
               3 => 'stop pending',
               4 => 'running',
               5 => 'resume pending',
               6 => 'pause pending',
               7 => 'paused');

checkService();

########
# SUBS
########


sub checkService() {
my $startCounter = 0;

Win32::Service::GetStatus('', $serviceName,  \%status);

if($status{"CurrentState"} eq '4') {
    # Log the event
    &logEvent("$currentTime:  $serviceName is running\n");
} elsif($status{"CurrentState"} eq '1') {

    Win32::Service::StartService('', $serviceName);
    }       
    while($startCounter < 3) {
        sleep(5);

        Win32::Service::GetStatus('', $serviceName,  \%status);

        if($status{"CurrentState"} eq '2') {
            $startCounter++;
        } else {
            $startCounter = 3;
        }
    }

    if($startCounter == 3) {
        &logEvent("$currentTime:  Unable to start $serviceName in $startCounter attempts\n");
    } else {
        &logEvent("$currentTime:  Started $serviceName in $startCounter attempts\n");
    }
}

sub getDate() {
my $year = $timeInfo[5] + 1900;
my $month = $timeInfo[4] + 1;
my $day = $timeInfo[3];
return sprintf("%04d-%02d-%02d", $year, $month, $day);
} 

sub getTime() {
my $hour = $timeInfo[2];
my $min = $timeInfo[1];
my $sec = $timeInfo[0];
return sprintf("%02d:%02d:%02d", $hour, $min, $sec);
}

sub logEvent() {
# Log the event
open(OUT, ">> C:/servicestatus/$currentDate.txt");
print OUT "$_[0]";
close(OUT);
}

Solution

  • Based upon some comments below (including some nice points by @Ron Bergin), I'm revising this post to show code that works for me (Windows 8.1, ActivePerl 5.16).

    #!/usr/local/bin/perl
    
    use strict;
    use warnings;
    
    use POSIX;
    use Win32::Service;
    
    my $currentDate = getDate();
    my %status;
    my %status_code = (
      Stopped => 1,
      StartPending => 2,
      StopPending => 3,
      Running => 4,
      ResumePending => 5,
      PausePending => 6,
      Paused => 7
    );
    
    checkService("Apple Mobile Device");
    
    ########
    # SUBS
    ########
    
    sub checkService {
      my $serviceName = shift || die "No arg passed";
      my $startCounter = 1;
      Win32::Service::GetStatus('', $serviceName, \%status);
      if ($status{"CurrentState"} eq $status_code{Running}) {
        logEvent("$serviceName is running\n");
      }
      elsif ($status{"CurrentState"} eq $status_code{'Stopped'}) {
        my $maxAttempts = 3;
        while ($startCounter <= $maxAttempts) {
          logEvent("Attempting to start $serviceName");
          Win32::Service::StartService('', $serviceName);
          sleep(5);
          Win32::Service::GetStatus('', $serviceName, \%status);
          if ($status{"CurrentState"} eq $status_code{Running}) {
            logEvent("Started $serviceName in $startCounter attempts\n");
            last;
          }
          $startCounter++;
        }
    
        if ($startCounter eq $maxAttempts) {
          logEvent("Unable to start $serviceName in $startCounter attempts\n");
        }
      }
    }
    
    sub getDate {
      my @timeInfo    = localtime(time);
      my $year  = $timeInfo[5] + 1900;
      my $month = $timeInfo[4] + 1;
      my $day   = $timeInfo[3];
      return sprintf("%04d-%02d-%02d", $year, $month, $day);
    }
    
    sub logEvent {
      my $msg = strftime("%H:%M:%S", localtime) . ": $_[0]\n";
      print "$msg";
      open(OUT, ">> C:/servicestatus/$currentDate.txt");
      print OUT "$msg";
      close(OUT);
    }
    

    Running this NOT as an admin, gives output like this:

    14:11:30: Attempting to start Apple Mobile Device
    14:11:35: Attempting to start Apple Mobile Device
    14:11:40: Attempting to start Apple Mobile Device
    

    Running as an admin looks like this:

    14:14:29: Attempting to start Apple Mobile Device
    14:14:34: Started Apple Mobile Device in 1 attempts