Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Validating that service is fully stopped in Windows

by DarthBobToo (Initiate)
on Jul 02, 2013 at 18:06 UTC ( #1042073=perlquestion: print w/ replies, xml ) Need Help??
DarthBobToo has asked for the wisdom of the Perl Monks concerning the following question:

O great holders of all Wisdom that is Perl, hear a petition from I, a humble grasshopper...

I am attempting to accomplish a small task using the Win32::Service. This task is:

  • Stop a service on my server.
  • Export specific data from the application for backup, using a pre-written script provided by the vendor.
  • Restart the service.

My issue is that when I stop the service, Win32::Service reports the service as stopped (status 0x01), but Windows shows the process is still running until it completely shuts down. If I kick the export off while the process is still running, it will fail. How can I validate that the process is stopped before moving on? This must be a commonly-asked question, but I haven't been able to find the answer.

Thank you.

JAPG (Just Another Perl Grasshopper)

Comment on Validating that service is fully stopped in Windows
Select or Download Code
Re: Validating that service is fully stopped in Windows
by dasgar (Deacon) on Jul 02, 2013 at 20:27 UTC

    Since you're working with Windows, it may be easier to utilize some of the utilities from the Sysinternals suite of tools. PsService might end up showing you the same thing that Windows' service manager is showing. Another alternative is the PsList, which provides information about running processes. You can have your script just do a system call to utilize these utilities.

    (NOTE: The first time you run one of the utilities from Sysinternals will have a GUI pop up dealing with the EULA. Subsequent times running the utilities does not encounter the EULA pop up.)

      use File::Fetch; my $ff = File::Fetch->new(uri => 'http://live.sysinternals.com/psservi +ce.exe'); my $where = $ff->fetch( to => $ENV{TEMP} || $ENV{TMP} ) or die $ff->er +ror; system $where, qw{ -? -accepteula /accepteula } ) ; ## run for each us +er
Re: Validating that service is fully stopped in Windows (pid)
by Anonymous Monk on Jul 02, 2013 at 20:28 UTC

    get the pid , you could use GetServices() to get shortname, then use Win32::Process::Info to associate shortname with a pid

    Once you have pid you might check if proc is alive with kill or http://search.cpan.org/perldoc/Win32::Process#Win32::Process::Open($obj,$pid,$iflags) or just sleep then enumerate all procs again

    Or you could use WMI, either like this (PID of Service) using DBD::WMI

    #!/usr/bin/perl use strict; use warnings; use DBI; use Win32::OLE qw(in); my $dbh = DBI->connect('dbi:WMI:'); my $sth = $dbh->prepare(<<WQL); SELECT * FROM Win32_Service WHERE Name = '$ARGV[0]' WQL $sth->execute(); if (my $row = $sth->fetchrow()) { printf( "%-20s - %10s %8i\n\t%s\n", $row->Name, $row->State, $row->ProcessID, $row->PathName ); }

    Or the same query using wmic

Re: Validating that service is fully stopped in Windows
by BrowserUk (Pope) on Jul 02, 2013 at 21:11 UTC

    Type: sc /? at a command line.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Validating that service is fully stopped in Windows
by DarthBobToo (Initiate) on Jul 03, 2013 at 14:50 UTC

    Thanks for the input. Because of the fact that I started with Perl, I decided to be stubborn and finish in Perl, even though the Sysinternals suite might've made more sense.

    Here's what I ended up with:

    #!/usr/bin/perl use v5.14; use strict; use warnings; use DBI; use Win32::Service; ## # Hostname of server where this script is being run. # my $hostname = `hostname`; chomp $hostname; ## # Reference to anonymous array returned by GetStatus. # my $w32ServiceStatus = {}; ## # Win32 API service status constants. # use constant { SERVICE_STOPPED => hex('0x00000001'), SERVICE_START_PENDING => hex('0x00000002'), SERVICE_STOP_PENDING => hex('0x00000003'), SERVICE_RUNNING => hex('0x00000004'), SERVICE_CONTINUE_PENDING => hex('0x00000005'), SERVICE_PAUSE_PENDING => hex('0x00000006'), SERVICE_PAUSED => hex('0x00000007'), }; ## # Additional script constants. # use constant { SLEEP_INTERVAL => 15, # Time to sleep bet +ween tries (sec.). MAX_WAIT_TIME => 15, # Max time to wait +for service to stop (min.). SERVICE_NAME => 'MY_SERVICE', # Service name. }; ###################################################################### +# # Get the current status of the service and stop it, if running. # Win32::Service::GetStatus('',SERVICE_NAME,$w32ServiceStatus); if ($w32ServiceStatus->{CurrentState} == SERVICE_RUNNING) { ## # Process ID. # my $pid = -999; ## # WMI database handle object. # my $dbh = DBI->connect('dbi:WMI:'); ## # WMI statement handle object. # my $sth = $dbh->prepare( sprintf ("SELECT * FROM Win32_Service WHERE Name = '%s'", SERVICE_NAME)); $sth->execute(); if (my $row = $sth->fetchrow()) { $pid = $row->ProcessID; } printf("Attempting to stop %s on $hostname...\n",SERVICE_NAME); ################################################################## +# # Stop the service. # Win32::Service::StopService('',SERVICE_NAME) or die sprintf("Unable to stop %s on %s: %s\n", SERVICE_NAME,$hostname,$!); printf("%s on %s stopping.\n",SERVICE_NAME,$hostname); ################################################################## +# # Continue to wait until the process is fully stopped. # my $stopCount = 0; while ($pid > 0 && $stopCount < (60 / SLEEP_INTERVAL * MAX_WAIT_TI +ME)) { sleep SLEEP_INTERVAL; $sth->execute(); if (my $row = $sth->fetchrow()) { $pid = $row->ProcessID; } $stopCount++; } ################################################################## +# # If the time taken to stop exceeds the maximum wait time, then # error out. # if ($stopCount < (60 / SLEEP_INTERVAL * MAX_WAIT_TIME)) { printf("%s stopped on %s.\n",SERVICE_NAME,$hostname); } else { die sprintf("Unable to stop %s on %s: %s\n", SERVICE_NAME,$hostname,$!); } } ###################################################################### +# # Service is not running. # else { printf("%s is not currently running on %s.\n",SERVICE_NAME,$hostna +me); } ###################################################################### +# # ...do whatever we're going to do before restarting the service... # ###################################################################### +# # Restart the service, if it was running to start with. # if ($w32ServiceStatus->{CurrentState} == SERVICE_RUNNING) { printf("Attempting to start %s on %s.\n",SERVICE_NAME,$hostname); Win32::Service::StartService('',SERVICE_NAME) or die sprintf("Unable to start %s on %s.\n",SERVICE_NAME, +$hostname); printf("%s on %s started.\n",SERVICE_NAME,$hostname); }
    JAPG (Just Another Perl Grasshopper)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1042073]
Approved by Perlbotics
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (9)
As of 2014-07-28 13:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (198 votes), past polls