Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Issues with Win32::Daemon

by Grygonos (Chaplain)
on Jan 09, 2004 at 19:29 UTC ( [id://320208]=perlquestion: print w/replies, xml ) Need Help??

Grygonos has asked for the wisdom of the Perl Monks concerning the following question:

Fellow Monks,

Frustration is setting in. I am trying to develop a Win32 service that will do data mining as requests are made to its queue, which it polls every 5 minutes. So I installed Win32::Daemon, installed the service using the following.

#!/perl -w use strict; use Win32::Daemon; my %service = (name => 'test', display => 'test', path => 'c:\\Perl\\bin\\perl.exe', pwd => '', parameters =>'q:\\test.pl',); if( Win32::Daemon::CreateService( \%service ) ) { print "Successfully added.\n"; } else { print "Failed to add service: " . Win32::FormatMessage( Win32::Dae +mon::GetLastError() ) . "\n"; }
added the following code to my script.
use Win32::Daemon; Win32::Daemon::StartService(); while(SERVICE_STOPPED != Win32::Daemon::State()) {sleep(1);} Win32::Daemon::State( SERVICE_RUNNING );

I received the same error listed in 89302: The service did not respond to the start or control request in a timely fashion.

I have read 89302. I don't understand the solution that fixed the problem presented by the poster. I did however try putting

BEGIN { open( STDERR, ">>c:/daemon.err" ); warn "$0 started ".localtime().$/; }
In my script to catch those errors... but it won't even show that it started... I have moved it around to quite a few places.

After realizing that it might be a problem with my script I simply set the scipt run by the service to be a script that writes 1..10 to a text file on C:\.. but to no avail the same msg is appearing.. does ANYONE have ANY idea?

p.s. yes I did super search this quite a bit and RTFM a few times.
edit Here's my code ... the service will now start... and it works... sorry for nt posting my code earlier .. but the whole node was lengthy enough already.
#!/perl -w use strict; use DBI; use Win32::Daemon; Win32::Daemon::StartService(); sleep (1) while(SERVICE_START_PENDING != Win32::Daemon::State()); Win32::Daemon::State(SERVICE_RUNNING); #Connect to the Queue my $queue = DBI->connect('dbi:ODBC:QUEUE','x','x',{AutoCommit=>1}) or +die "$!"; writeLogEntry(Win32::Daemon::State()); #Declare Daemon Variables my $query; my @queries; my $sth; my $status = Win32::Daemon::State(); while(1) { writeLogEntry("Waiting for Mining Request...\n"); #Get the highest priority request that is not completed $query = q{SELECT MIN(priority), ConfigFile FROM Queue WITH (NOLOCK) WHERE Status <> ? AND Status <> ? GROUP BY ConfigFile}; $sth = $queue->prepare($query); $sth->execute("c","f"); my @row = $sth->fetchrow_array; $sth->finish(); #sleep if the priority is null (ie. the query returned the default + row) next if !$row[0]; writeLogEntry("===========================================\n"); writeLogEntry("Received request with priority: ".$row[0],"v"); writeLogEntry("Retrieving Queries..","v"); @queries = getBatchQueries($row[1]); #Get the queries to be ran if(@queries > 0) { if(runBatchQueries(\@queries,\$queue)) { $row[1] =~ m{([\w\d\.\+\-\=\(\)\%\^\$\#\@\!\~\`\']*)$}; rename $row[1], "C:\\SQL_Server_Mining\\Queue\\Completed\\ +".$1; writeLogEntry("Completed Mining!\n"); writeLogEntry("=========================================== +\n"); } } else { writeLogEntry("Retrieval of Queries FAILED for ".$row[1]."!"); } sleep(300); } Win32::Daemon::StopService(); #Runs queries specified in batch_list.txt sub runBatchQueries { #Get query list and db handle my ($queries,$q) = @_; my $client = shift @$queries; my $id = shift @$queries; my $query = q{SELECT DatabaseName FROM Databases WITH (NOLOCK) WHERE ClientCode = ?}; my $sth = $$q->prepare($query); $sth->execute($client); my $dbname = $sth->fetchrow_arrayref; my $dbh = DBI->connect('dbi:ODBC:'.$$dbname[0],'x','x'); my $rows = 0; #Get the values from localtime my @time = (localtime) [0..5]; #Construct the date my $date_time = ($time[5] + 1900)."-".($time[4] + 1)."-".$time[3]. +"_".$time[2].".".$time[1].".".$time[0]; mkdir "Q:\\Results\\$date_time"; #Run each query foreach my $item(@$queries) { #Clean out query $query = undef; #remove the newline from the filename chomp $item; writeLogEntry("Loading ".$item.".."); #Open the current file open(QUERY,"<".$item) || do{warn "Could not open $_::$!"; writ +eLogEntry("$_ failed to open!");}; #Read the file into a scalar for execution while(<QUERY>) { $query .= $_ . " "; chomp($query); } close QUERY; #Prepare the query $sth = $dbh->prepare($query); writeLogEntry("Executing ".$item."..","v"); #Execute the query $sth->execute(); writeLogEntry("Writing results for ".$item."..","v"); #grab the file name w/o extension $item =~ m{([\w\d\.\+\-\=\(\)\%\^\$\#\@\!\~\`\']+).sql$}; #Open the results file open(OUTPUT,">C:\\SQL_Server_Mining\\Results\\".$date_time."\\ +".$1."_results.txt") || do{warn "Could not open ".$item."::".$!; writ +eLogEntry($item." failed to open!");}; $rows = 0; #Write the results while(my @row = $sth->fetchrow_array) { $rows++; #Set output delimiter to the | $,="|"; #Remove trailing spaces foreach(@row) {s/\s*$//g} print OUTPUT @row ,"\n"; } #close the file close OUTPUT; #Output the number of rows affected writeLogEntry("Wrote ".$rows." results to ".$1."_results.txt." +,"v"); } ##UPDATE THE QUEUE## $query = q{UPDATE Queue SET Status = ? WHERE RequestID = ?}; $sth = $$q->prepare($query); $sth->execute("c",$id); #################### return 1; } #Gets the queries to be ran sub getBatchQueries { my $file = shift; open(LIST,"<Q:\\Queue\\".$file) || do{return 0;}; #Get the files to be executed my @queries = <LIST>; close LIST; #remove newlines and trailing spaces foreach(@queries) { chomp; s/\s*$//g; } return @queries; } sub writeLogEntry { #Get the parameters my ($entry,$mode) = @_; #Open the log file open(LOG,">>C:\\SQL_Server_Mining\\query_log.txt") || warn "Failed + to open query_log.txt see Administrator!\n"; #Write the actual log entry print LOG localtime()."::".$entry."\n"; if($mode) { #If verbose mode is selected if(uc($mode) eq "V") { #echo the log entry print $entry."\n"; } } #Write dash seperator for next entry print LOG "-" for 0..50; #Write a newline print LOG "\n"; close LOG; }

Grygonos

Replies are listed 'Best First'.
Re: Issues with Win32::Daemon
by gooch (Monk) on Jan 09, 2004 at 21:40 UTC
    Having done a handful of successful services using Win32Daemon, I will give what help I can. The Windows Service Manager is a bit - picky - about how you talk to it, and how fast you respond. As you didn't provide very much of a code sample, I am going to show you the skeleton startup section that I use in every service script I have made to date - and hope that it will provide at least some assistance. You are welcome to /msg me on chatterbox if you like, as well.
      Seeing this is a Windows app, you might also want to look at PAR (par.perl.org -- not just for Windows apps) to compile your script down to an exe, rather than trying to run Perl against it with a file parameter. This would allow for easier distribution, though it probably won't fix your Win32::Daemon problems :)
Re: Issues with Win32::Daemon
by pilgrim (Monk) on Jan 09, 2004 at 20:25 UTC

    Well, it seems a bit obvious, but I'll ask anyway:

    Have you tried moving test.pl to your c: drive and changing the parameters hash value?

    (Maybe it can't run the script on q:, whatever drive that is.)

    --pilgrim
Re: Issues with Win32::Daemon
by rchiav (Deacon) on Jan 09, 2004 at 21:15 UTC
    You said that you've RTFM, but you seem to be under the impression that Win32::Daemon is only for installing the service. While you can install a service with Win32::Daemon, you need to use the functions of Win32::Daemon within your script that is going to become a service. Did you read all the examples at the bottom of the docs? They all show how it's used. If I take a script that writes to a file and use Win32::Daemon to install it as a service, it's going to tell me that it didn't start.
      No I know that.. If you read my post it said I added the daemon functions to my script (implying the service itself) I'm not that dense. It was however the network drive issue. I had q: mapped to a local folder on my drive.. so that others could use it.. and i mapped it as well jsut for convenience. Switching it to the local filesystem folder fixed it.

      Grygonos
        You've since edited your node and added the code so it's more clear exactly what you're doing. The reason I got the impression that you wern't seeing everything that needed to happen was because you originally said that you added a couple of lines, which did not include notifying the service manager that the service started.

        Glad you got it fixed.

Re: Issues with Win32::Daemon
by jbware (Chaplain) on Jan 09, 2004 at 21:30 UTC
    I'm no services expert, so I apologize ahead of time if I missed any service idiosyncrasies, but I hacked a service script together that works at a basic level. Below is the code I have that will properly start and stop w/ no errors. It doesn't include all the pausing, restarting, etc functionality, but it should provide a foundation to build on. All the code is taken from the examples section of the Roth's Consulting site ( http://www.roth.net/perl/Daemon/ ) I stripped it down alot and changed what I felt were typos. If nothing else, this should help to get you started.
    use Win32::Daemon; $SERVICE_SLEEP_TIME = 20; Win32::Daemon::StartService(); sleep (1) while(SERVICE_START_PENDING != Win32::Daemon::State()); Win32::Daemon::State(SERVICE_RUNNING); $dontStop = 1; $count=0; # Note: the $count stuff is here in case i can't stop it.. purely for +debugging while (($dontStop) && ($count++ < 600)) { # Process stuff here open(OUT,">>e:\\temp3\\testout.txt"); print OUT localtime(); print OUT " $_\n" for (1..10); close(OUT); if(SERVICE_CONTROL_NONE != ($Message = Win32::Daemon::QueryLastMes +sage())) { if(SERVICE_CONTROL_INTERROGATE == $Message) { Win32::Daemon::State($PrevState); } elsif(SERVICE_CONTROL_STOP == $Message) { Win32::Daemon::State(SERVICE_STOP_PENDING, 25000); $dontStop = 0; } } Win32::Sleep($SERVICE_SLEEP_TIME); } Win32::Daemon::StopService();

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://320208]
Approved by monktim
Front-paged by monktim
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2025-03-19 18:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When you first encountered Perl, which feature amazed you the most?










    Results (59 votes). Check out past polls.