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

hello monks!

I have read the documentation about this module but I register many understanding problems:

1)on my machine the module only work if it is in Win32/service/daemon (??)
2)in the dave roth example in th official page of win32 daemon there are 2 examples: the first to install a service: can I install another script as a daemon with this script? The second is a skeleton prototype of a service: there is a place commented that tell insert here the main code: I have tried to insert a stupid test code like:
sleep 5; system 'net send Administrator HELLO!';
but the skeleton code then stop the service. Why?

May be I need 2 scripts? the first with the control of the state + the main code and a second to install the service?
In any case when the Daemon tell me that the service is started succesfully I can't start it for reasons of timely or log on (it not accept my admin usr\pwd!)
any example or suggestion(coming back to the field?)?

greetings from sweet-sunny roma
lor*

Replies are listed 'Best First'.
Re: win32::Daemon (stupid) questions
by blm (Hermit) on Oct 15, 2002 at 12:44 UTC

    In the examples the functionality to "Create a Service" is in a different script but you could have that in the same script. You could put the install routine in a sub that only runs when a certian parameter is added eg --install. I have seen binary services written in C that implement things this way. IMHO the install routine simply adds the appropriate registry settings so the Service Control Manager can find the perl interpreter and give it the first parameter which is the full path of the perl script. The Service Control Manager is then responsible for starting, restarting and stopping your service.

    AFAIK the "Not in timely fashion" error that you may see when getting the Service Control Manager to start the service is because the script did not notify the Service Control Manager of successful start up before a timeout.

    --blm--

      AFAIK the "Not in timely fashion" error that you may see when getting the Service Control Manager to start the service is because the script did not notify the Service Control Manager of successful start up before a timeout.

      I also see this when I have errors in my script. But of course I test them before I load them as a service..;) well not always... hence that error message.

      What I think you will need is the following

      } elsif( SERVICE_RUNNING == $State ) { # The service is running as normal... system('net send 127.0.0.1 Hello'); sleep 5; } else { # We have some unknown state... # reset it back to what we last knew the state to be... Win32::Daemon::State("$PrevState"); sleep( $timeout ); }

      -----
      Of all the things I've lost in my life, its my mind I miss the most.
Re: win32::Daemon (stupid) questions
by AcidHawk (Vicar) on Oct 17, 2002 at 07:06 UTC

    Discipulus asked me to post a sample.

    This one worked when I did a little testing a while back... hence no strict or warnings... forgive me...

    #!perl.exe ###################################################################### +################## ## ## Test Service v 1.2 - Script to test ser +vice ## ###################################################################### +################## use Getopt::Long; use Win32; use Win32::Daemon; my %Config = (timeout_value => 2, log_file => join( "", Win32::GetFullPathName( $0 ) ), ); $Config{log_file} =~ s/[^.]*?$/log/; Getopt::Long::Configure( "prefix_pattern=(-|\/)" ); $Result = GetOptions( \%Config, qw( install|i remove|r timeout_value|t=i log_file|l=s account_id|user=s account_password|pass=s help|?|h ) ); $Config{help} = 1 if( ! $Result || scalar @ARGV ); if( $Config{install}) { &Install(); exit(); } elsif( $Config{remove}) { &Remove(); exit(); } elsif( $Config{help}) { &Syntax(); exit(); } #Open Log File if( open( LOG, ">>$Config{log_file}" ) ) { my $TempSelect = select( LOG ); $| = 1; select( $TempSelect ); print LOG "# Date: " . localtime() . "\n=================\n"; } if( ! Win32::Daemon::StartService()) { if( fileno( LOG ) ) { print LOG "Failed to start this script as a Win32 service.\n"; print LOG "Error: " . GetError() . "\n"; close( LOG ); } exit(); } $PrevState = SERVICE_STARTING; $cnt=0; while( SERVICE_STOPPED != ( $State = Win32::Daemon::State() ) ) { if( SERVICE_START_PENDING == $State ) { # Initialization code Win32::Daemon::State( SERVICE_RUNNING ); $PrevState = SERVICE_RUNNING; } elsif( SERVICE_PAUSE_PENDING == $State ) { # "Pausing..."; Win32::Daemon::State( SERVICE_PAUSED ); print LOG "Service is Paused \n"; $PrevState = SERVICE_PAUSED; next; } elsif( SERVICE_CONTINUE_PENDING == $State ) { # "Resuming..."; Win32::Daemon::State( SERVICE_RUNNING ); print LOG "Service Continue\n"; $PrevState = SERVICE_RUNNING; next; } elsif( SERVICE_STOP_PENDING == $State ) { # "Stopping..."; Win32::Daemon::State( SERVICE_STOPPED ); $PrevState = SERVICE_STOPPED; next; } elsif( SERVICE_RUNNING == $State ) { # The service is running as normal... $cnt++; print LOG "Sending $cnt \n"; system("net send 127.0.0.1 \"Hello\""); sleep 10; $PrevState = SERVICE_RUNNING; } else { # We have some unknown state... # reset it back to what we last knew the state to be... Win32::Daemon::State( $PrevState ); sleep( $Config{timeout_value} ); } } #Stop the Service Win32::Daemon::StopService(); if( fileno( LOG ) ) { print LOG "================================\n"; print LOG "Service Stopped.\n " . localtime() . "\n"; close( LOG ); } ###################################################################### +################## ## ## SUB ROUTINES ## ###################################################################### +################## #Configuration for Service sub GetServiceConfig { my $script_path = join("",Win32::GetFullPathName($0)); my %hash = ( name => 'X-TmpSvc', display => 'X-TmpSvc', path => $^X, user => $config{account_id}, password => $config{account_password}, parameters => "$script_path -l \"$Config{log_file}\" -t \"$ +Config{timeout_value}\"", ); return(\%hash); } #Install Service sub Install { my $service_config = GetServiceConfig(); if (Win32::Daemon::CreateService($service_config)) { print "The $service_config->{display} was Successfully install +ed.\n"; } else { print "Failed to Install $service_config->{display} service.\n +Error: " . GetError() . "\n"; } } #Remove Service sub Remove { my $service_config = GetServiceConfig(); if( Win32::Daemon::DeleteService( $service_config->{name} ) ) { print "The $service_config->{display} was successfully removed +.\n"; } else { print "Failed to remove the $service_config->{display} service +.\nError: " . GetError() . "\n"; } } #Display if no Command Line Arguments Found! sub Syntax { print << "EOT"; A Simple Win32 service Syntax: [-l <Path>] [-t <Time>] [-remove][-install [-user <User> -pass + <Pwd}]] -t <Time>.......Time in seconds to wait per check. This is the mai +n loop sleep time so a long value will slow service updat +es. -l <Path>.......Path to store the log file. Make this an empty str +ing ("") to disable logging (making this service usele +ss). Default: $Config{log_file} -user <User>....User account the service is to run under. -pass <Pwd>.....The user account's password. -install........Installs this script as a Win32 service. Any additional parameters passed in will set be wh +at the script uses when running as a service. -remove.........Removes this script as a Win32 service. Examples +: perl $0 -install perl $0 -install -user Domain\\User -pass UserPassword -l c:\\moni +tor.log -d c:\\uploads perl $0 -remove perl $0 -l "c:\\winnt\\system32\\logfiles\\monitor.log" -t 120 EOT } #Display Errors sub GetError { return( Win32::FormatMessage( Win32::Daemon::GetLastError() ) ); }

    -----
    Of all the things I've lost in my life, its my mind I miss the most.