Windows services in PERL

Windows services in PERL

am 13.07.2006 21:01:48 von harvar007

Hi

I am trying to create a win32 service using the module win32:deamon. I
wrote a simple code and tried to get that running before I went to the
actual one. I am actually able to successfully create the service and
see the same in the Management Console, but when I try to right click
and say Start I get "error :1053 the service did not respond or start
to the control request in a timely fashion"

Can any one please, let me know what might be wrong in this scenario?

Here is my sample code which I was trying to get installed!

use Win32::Daemon;
Win32::Daemon::StartService();
while( SERVICE_START_PENDING != Win32::Daemon::State() )
{
sleep( 1 );
}
Win32::Daemon::State( SERVICE_RUNNING );
unlink( glob( "c:\\temp\\*.tmp" ) );
Win32::Daemon::StopService();

Thanks
Harini

Re: Windows services in PERL

am 14.07.2006 17:48:31 von unknown

harvar007@yahoo.com wrote:
> Hi
>
> I am trying to create a win32 service using the module win32:deamon. I
> wrote a simple code and tried to get that running before I went to the
> actual one. I am actually able to successfully create the service and
> see the same in the Management Console, but when I try to right click
> and say Start I get "error :1053 the service did not respond or start
> to the control request in a timely fashion"
>
> Can any one please, let me know what might be wrong in this scenario?
>
> Here is my sample code which I was trying to get installed!
>
> use Win32::Daemon;
> Win32::Daemon::StartService();
> while( SERVICE_START_PENDING != Win32::Daemon::State() )
> {
> sleep( 1 );
> }
> Win32::Daemon::State( SERVICE_RUNNING );
> unlink( glob( "c:\\temp\\*.tmp" ) );
> Win32::Daemon::StopService();
>
> Thanks
> Harini
>

It has been a while, but ...

The first suggestion I have is to check the success of
Win32::Daemon::StartService (), with something like

Win32::Daemon::StartService () or do {
my $err = "Failed to start service\n" .
Win32::FormatMessage (
Win32::Daemon::GetLastError ());
# Log the error somewhere, then
die $err;
};

The second is that you probably want to handle the SERVICE_NOT_READY
state by going to state SERVICE_START_PENDING. In fact, the more I think
about it, the more I think this may be your problem. Maybe your event
loop should be something like

while (1)
{
my $state = Win32::Daemon::State ();
if ($state == SERVICE_NOT_READY)
{
Win32::Daemon::State (SERVICE_START_PENDING);
} elsif ($state == SERVICE_START_PENDING)
{
last;
}
sleep (1); # or Win32::Sleep (1000);
}

Less likely, but possible:

* You might need to set the state to SERVICE_RUNNING in response to the
SERVICE_CONTINUE_PENDING state, in addition to the SERVICE_START_PENDING
state.

* Jenda's code (see below) sets the state to SERVICE_RUNNING in response
to state 0x0080. You might want to try the same, in addition to the others.

* You _might_ also need to respond to the OS messages you get from
calling Win32::Daemon::QueryLastMessage -- at least to
SERVICE_CONTROL_INTERROGATE (respond with the state you believe the
service to be in) in your event loop. If your event loop ran
indefinitely you might want to respond to SERVICE_CONTROL_SHUTDOWN
(system shutdown) by setting your service to SERVICE_STOP_PENDING and
cleaning up.

Better than all this, though, is a trick I picked up from Jenda
Krynicky's Win32::Daemon::Simple (see http://jenda.krynicky.cz/). I did
not use this module itself because it required replacing ActiveState's
Win32::Registry with an incompatible version from Jenda, and I didn't
want to do that because it made an otherwise-straightforward maintenance
situation complicated. Of course, the trade-off was that an otherwise
simple daemon became complicated.

The trick allows you to run your service interactively (i.e. not as a
service, but so that you actually see the output), and the essence of
the trick is the following:


# After you have successfully called Win32::Daemon::StartService:

my $save_state = SERVICE_NOT_READY; # in case interactive.


# Wherever you query the service state, code

service_state ();

# Wherever you set the service state, code

service_state ($whatever_the_new_state_is);

# As a special case of the above, if you are responding to
# SERVICE_CONTROL_INTERROGATE (see above), code

service_state ($save_state);


###############################
#
# With your other internal subroutines:


# Return true if running from the command line, false otherwise.

BEGIN {
my $cmdlin = Win32::Console::_GetConsoleTitle () ? 1 : 0;
sub CMDLINE {$cmdlin}
}

# Wrap Win32::Daemon::State so we can run interactively.

sub service_state {
return CMDLINE () ? $save_state : Win32::Daemon::State ()
unless @_;
push @_, 25000 # Milliseconds
if $_[0] == SERVICE_STOP_PENDING && @_ == 1;
Win32::Daemon::State (@_) unless CMDLINE ();
$save_state = shift;
return $save_state;
}

One last thought: You might think about logging to a file, so you can
tell what your service is doing.

Tom Wyant

Re: Windows services in PERL

am 14.07.2006 18:15:36 von harvar007

Hi Tom,

Thanks a ton for the eloborate suggestions! Will try them and let you
know my outcome...

Harini

harryfmudd [AT] comcast [DOT] net wrote:
> harvar007@yahoo.com wrote:
> > Hi
> >
> > I am trying to create a win32 service using the module win32:deamon. I
> > wrote a simple code and tried to get that running before I went to the
> > actual one. I am actually able to successfully create the service and
> > see the same in the Management Console, but when I try to right click
> > and say Start I get "error :1053 the service did not respond or start
> > to the control request in a timely fashion"
> >
> > Can any one please, let me know what might be wrong in this scenario?
> >
> > Here is my sample code which I was trying to get installed!
> >
> > use Win32::Daemon;
> > Win32::Daemon::StartService();
> > while( SERVICE_START_PENDING != Win32::Daemon::State() )
> > {
> > sleep( 1 );
> > }
> > Win32::Daemon::State( SERVICE_RUNNING );
> > unlink( glob( "c:\\temp\\*.tmp" ) );
> > Win32::Daemon::StopService();
> >
> > Thanks
> > Harini
> >
>
> It has been a while, but ...
>
> The first suggestion I have is to check the success of
> Win32::Daemon::StartService (), with something like
>
> Win32::Daemon::StartService () or do {
> my $err = "Failed to start service\n" .
> Win32::FormatMessage (
> Win32::Daemon::GetLastError ());
> # Log the error somewhere, then
> die $err;
> };
>
> The second is that you probably want to handle the SERVICE_NOT_READY
> state by going to state SERVICE_START_PENDING. In fact, the more I think
> about it, the more I think this may be your problem. Maybe your event
> loop should be something like
>
> while (1)
> {
> my $state = Win32::Daemon::State ();
> if ($state == SERVICE_NOT_READY)
> {
> Win32::Daemon::State (SERVICE_START_PENDING);
> } elsif ($state == SERVICE_START_PENDING)
> {
> last;
> }
> sleep (1); # or Win32::Sleep (1000);
> }
>
> Less likely, but possible:
>
> * You might need to set the state to SERVICE_RUNNING in response to the
> SERVICE_CONTINUE_PENDING state, in addition to the SERVICE_START_PENDING
> state.
>
> * Jenda's code (see below) sets the state to SERVICE_RUNNING in response
> to state 0x0080. You might want to try the same, in addition to the others.
>
> * You _might_ also need to respond to the OS messages you get from
> calling Win32::Daemon::QueryLastMessage -- at least to
> SERVICE_CONTROL_INTERROGATE (respond with the state you believe the
> service to be in) in your event loop. If your event loop ran
> indefinitely you might want to respond to SERVICE_CONTROL_SHUTDOWN
> (system shutdown) by setting your service to SERVICE_STOP_PENDING and
> cleaning up.
>
> Better than all this, though, is a trick I picked up from Jenda
> Krynicky's Win32::Daemon::Simple (see http://jenda.krynicky.cz/). I did
> not use this module itself because it required replacing ActiveState's
> Win32::Registry with an incompatible version from Jenda, and I didn't
> want to do that because it made an otherwise-straightforward maintenance
> situation complicated. Of course, the trade-off was that an otherwise
> simple daemon became complicated.
>
> The trick allows you to run your service interactively (i.e. not as a
> service, but so that you actually see the output), and the essence of
> the trick is the following:
>
>
> # After you have successfully called Win32::Daemon::StartService:
>
> my $save_state = SERVICE_NOT_READY; # in case interactive.
>
>
> # Wherever you query the service state, code
>
> service_state ();
>
> # Wherever you set the service state, code
>
> service_state ($whatever_the_new_state_is);
>
> # As a special case of the above, if you are responding to
> # SERVICE_CONTROL_INTERROGATE (see above), code
>
> service_state ($save_state);
>
>
> ###############################
> #
> # With your other internal subroutines:
>
>
> # Return true if running from the command line, false otherwise.
>
> BEGIN {
> my $cmdlin = Win32::Console::_GetConsoleTitle () ? 1 : 0;
> sub CMDLINE {$cmdlin}
> }
>
> # Wrap Win32::Daemon::State so we can run interactively.
>
> sub service_state {
> return CMDLINE () ? $save_state : Win32::Daemon::State ()
> unless @_;
> push @_, 25000 # Milliseconds
> if $_[0] == SERVICE_STOP_PENDING && @_ == 1;
> Win32::Daemon::State (@_) unless CMDLINE ();
> $save_state = shift;
> return $save_state;
> }
>
> One last thought: You might think about logging to a file, so you can
> tell what your service is doing.
>
> Tom Wyant

Re: Windows services in PERL

am 14.07.2006 21:30:05 von harini.gopi

that didnt work either!
so i downloaded an utility called "srvany.exe" which apparently seems
to have fixed the problem! am not sure though why it couldnt start in
the normal manner...

Harini

harryfmudd [AT] comcast [DOT] net wrote:
> harvar007@yahoo.com wrote:
> > Hi
> >
> > I am trying to create a win32 service using the module win32:deamon. I
> > wrote a simple code and tried to get that running before I went to the
> > actual one. I am actually able to successfully create the service and
> > see the same in the Management Console, but when I try to right click
> > and say Start I get "error :1053 the service did not respond or start
> > to the control request in a timely fashion"
> >
> > Can any one please, let me know what might be wrong in this scenario?
> >
> > Here is my sample code which I was trying to get installed!
> >
> > use Win32::Daemon;
> > Win32::Daemon::StartService();
> > while( SERVICE_START_PENDING != Win32::Daemon::State() )
> > {
> > sleep( 1 );
> > }
> > Win32::Daemon::State( SERVICE_RUNNING );
> > unlink( glob( "c:\\temp\\*.tmp" ) );
> > Win32::Daemon::StopService();
> >
> > Thanks
> > Harini
> >
>
> It has been a while, but ...
>
> The first suggestion I have is to check the success of
> Win32::Daemon::StartService (), with something like
>
> Win32::Daemon::StartService () or do {
> my $err = "Failed to start service\n" .
> Win32::FormatMessage (
> Win32::Daemon::GetLastError ());
> # Log the error somewhere, then
> die $err;
> };
>
> The second is that you probably want to handle the SERVICE_NOT_READY
> state by going to state SERVICE_START_PENDING. In fact, the more I think
> about it, the more I think this may be your problem. Maybe your event
> loop should be something like
>
> while (1)
> {
> my $state = Win32::Daemon::State ();
> if ($state == SERVICE_NOT_READY)
> {
> Win32::Daemon::State (SERVICE_START_PENDING);
> } elsif ($state == SERVICE_START_PENDING)
> {
> last;
> }
> sleep (1); # or Win32::Sleep (1000);
> }
>
> Less likely, but possible:
>
> * You might need to set the state to SERVICE_RUNNING in response to the
> SERVICE_CONTINUE_PENDING state, in addition to the SERVICE_START_PENDING
> state.
>
> * Jenda's code (see below) sets the state to SERVICE_RUNNING in response
> to state 0x0080. You might want to try the same, in addition to the others.
>
> * You _might_ also need to respond to the OS messages you get from
> calling Win32::Daemon::QueryLastMessage -- at least to
> SERVICE_CONTROL_INTERROGATE (respond with the state you believe the
> service to be in) in your event loop. If your event loop ran
> indefinitely you might want to respond to SERVICE_CONTROL_SHUTDOWN
> (system shutdown) by setting your service to SERVICE_STOP_PENDING and
> cleaning up.
>
> Better than all this, though, is a trick I picked up from Jenda
> Krynicky's Win32::Daemon::Simple (see http://jenda.krynicky.cz/). I did
> not use this module itself because it required replacing ActiveState's
> Win32::Registry with an incompatible version from Jenda, and I didn't
> want to do that because it made an otherwise-straightforward maintenance
> situation complicated. Of course, the trade-off was that an otherwise
> simple daemon became complicated.
>
> The trick allows you to run your service interactively (i.e. not as a
> service, but so that you actually see the output), and the essence of
> the trick is the following:
>
>
> # After you have successfully called Win32::Daemon::StartService:
>
> my $save_state = SERVICE_NOT_READY; # in case interactive.
>
>
> # Wherever you query the service state, code
>
> service_state ();
>
> # Wherever you set the service state, code
>
> service_state ($whatever_the_new_state_is);
>
> # As a special case of the above, if you are responding to
> # SERVICE_CONTROL_INTERROGATE (see above), code
>
> service_state ($save_state);
>
>
> ###############################
> #
> # With your other internal subroutines:
>
>
> # Return true if running from the command line, false otherwise.
>
> BEGIN {
> my $cmdlin = Win32::Console::_GetConsoleTitle () ? 1 : 0;
> sub CMDLINE {$cmdlin}
> }
>
> # Wrap Win32::Daemon::State so we can run interactively.
>
> sub service_state {
> return CMDLINE () ? $save_state : Win32::Daemon::State ()
> unless @_;
> push @_, 25000 # Milliseconds
> if $_[0] == SERVICE_STOP_PENDING && @_ == 1;
> Win32::Daemon::State (@_) unless CMDLINE ();
> $save_state = shift;
> return $save_state;
> }
>
> One last thought: You might think about logging to a file, so you can
> tell what your service is doing.
>
> Tom Wyant