http://www.perlmonks.org?node_id=994376

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

I'm trying to run a perl script as a service, but as myself as well. I want it to start when the computer boots up and run continuously. This is using IEInspector's libraries to grab all http requests and save them out to a file periodically. When I run it under the LocalSystem account, I don't get the websurfing that I do and need it to grab, just the http requests that the LocalSystem's processes are sending.

So, I attempted to install the service so that it would run as me in the hopes that I will get my surfing without having to start the analyzer myself. Unfortunately, I get the following error:

Windows could not start the HTMLReqCapture service on Local Computer.
Error 1069: The service did not start due to a logon failure.

The code is below:

use strict; use warnings; use Win32; use Win32::OLE; use Win32::Daemon; use Net::FTP; use constant SERVICE_NAME => 'HTMLReqCapture'; use constant SERVICE_DESC => 'HTML Request Capture Service'; use constant false => 0; use constant true => 1; my $HTTPAnalyzer; my $tempvar = 'uninit'; main(); sub main { # Get command line argument - if none passed, use empty string my $opt = shift (@ARGV) || ""; # Check command line argument if ($opt =~ /^(-i|--install)$/i) { install_service(SERVICE_NAME, SERVICE_DESC); } elsif ($opt =~ /^(-r|--remove)$/i) { remove_service(SERVICE_NAME); } elsif ($opt =~ /^(--run)$/i) { # Redirect STDOUT and STDERR to a log file # Derive the name of the file from the name of the program # The log file will be in the scripts directory, with extension .l +og my ($cwd,$bn,$ext) = ( Win32::GetFullPathName($0) =~ /^(.*\\)(.*)\.(.*)$/ ) [0..2] ; my $log = $cwd . $bn . ".log"; # Redirect STDOUT and STDERR to log file open(STDOUT, ">> $log") or die "Couldn't open $log for appending: +$!\n"; open(STDERR, ">&STDOUT"); # Autoflush, no buffering $|=1; # Register the events which the service responds to Win32::Daemon::RegisterCallbacks( { start => \&Callback_Start, running => \&Callback_Running, stop => \&Callback_Stop, pause => \&Callback_Pause, continue => \&Callback_Continue, } ); my %Context = ( last_state => SERVICE_STOPPED, start_time => time(), ); # Start the service passing in a context and indicating to callbac +k # using the "Running" event every 300000 milliseconds (5 minutes). # NOTE: the StartService method with in 'callback mode' will block +, in other # words it won't return until the service has stopped, but the cal +lbacks below # will respond to the various events - START, STOP, PAUSE etc... print "Starting service...\n"; Win32::Daemon::StartService( \%Context, 300000 ); # Here the service has stopped close STDERR; close STDOUT; } else { print "No valid options passed - nothing done\n"; } } sub Callback_Running { my( $Event, $Context ) = @_; my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = l +ocaltime(time); my $timestamp = sprintf("%02d:%02d:%02d", $hour, $min, $sec); print "Time entering callback_running is $timestamp\n"; $timestamp = sprintf("%02d%02d%02d", $hour, $min, $sec); my $filename = "c:\\agentName_ip_$timestamp.xml"; $HTTPAnalyzer->SaveLog($filename, 0 ); print "$timestamp: log saved, about to clear...\n"; $HTTPAnalyzer->Clear(); ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = loca +ltime(time); $timestamp = sprintf("%02d:%02d:%02d", $hour, $min, $sec); print "The time leaving callback_running is $timestamp\n"; } sub Callback_Start { my( $Event, $Context ) = @_; print "Starting...\n"; # Create HTTPAnalyzer Stand-Alone Object $HTTPAnalyzer = Win32::OLE->new('HttpAnalyzerStd.HTTPAnalyzerStandAl +one'); $HTTPAnalyzer->{Visible}=false; print "About to start analyzing\n"; $HTTPAnalyzer->AttachAllSessions(); $HTTPAnalyzer->Start(); $tempvar = 'started'; $Context->{last_state} = SERVICE_RUNNING; Win32::Daemon::State( SERVICE_RUNNING ); } sub Callback_Pause { my( $Event, $Context ) = @_; print "Pausing...\n"; $Context->{last_state} = SERVICE_PAUSED; Win32::Daemon::State( SERVICE_PAUSED ); } sub Callback_Continue { my( $Event, $Context ) = @_; print "Continuing...\n"; $Context->{last_state} = SERVICE_RUNNING; Win32::Daemon::State( SERVICE_RUNNING ); } sub Callback_Stop { my( $Event, $Context ) = @_; print "Stopping...\n"; $HTTPAnalyzer->stop(); $tempvar = 'stop'; $Context->{last_state} = SERVICE_STOPPED; Win32::Daemon::State( SERVICE_STOPPED ); # We need to notify the Daemon that we want to stop callbacks and th +e service. Win32::Daemon::StopService(); } sub install_service { my ($srv_name, $srv_desc) = @_; my ($path, $parameters); # Get the program's full filename, break it down into constituent p +arts my $fn = Win32::GetFullPathName($0); my ($cwd,$bn,$ext) = ( $fn =~ /^(.*\\)(.*)\.(.*)$/ ) [0..2] ; # Determine service's path to executable based on file extension if ($ext eq "pl") { # Source perl script - invoke perl interpreter $path = "\"$^X\""; # Parameters include extra @INC directories and perl script # @INC directories must not end in \ otherwise perl hangs my $inc = ($cwd =~ /^(.*?)[\\]?$/) [0]; # The command includes the --run switch needed in main() $parameters = "-I " . "\"$inc\"" . " \"$fn\" --run"; } elsif ($ext eq "exe") { # Compiled perl script - invoke the compiled script $path = "\"$fn\""; $parameters = ""; } else { # Invalid file type? die "Can not install service for $fn, file extension $ext not supported\n"; } my $username = "mydomain\\myusername"; my $pword = "MyPassw0rd"; # Populate the service configuration hash # The hash is required by Win32::Daemon::CreateService my %srv_config = ( name => $srv_name, display => $srv_name, path => $path, description => $srv_desc, parameters => $parameters, service_type => SERVICE_WIN32_OWN_PROCESS, start_type => SERVICE_AUTO_START, user => $username, password => $pword ); # Install the service if( Win32::Daemon::CreateService( \%srv_config ) ) { print "Service installed successfully\n"; } else { print "Failed to install service\n"; } } sub remove_service { my ($srv_name, $hostname) = @_; $hostname ||= Win32::NodeName(); if ( Win32::Daemon::DeleteService ( $srv_name ) ) { print "Service uninstalled successfully\n"; } else { print "Failed to uninstall service\n"; } }

Replies are listed 'Best First'.
Re: Win32::Daemon running as user
by Anonymous Monk on Sep 18, 2012 at 23:11 UTC

    Error 1069: The service did not start due to a logon failure.

    run services.msc and set the logon details manually, and try to get it working that way

Re: Win32::Daemon running as user
by fluffyvoidwarrior (Monk) on Sep 19, 2012 at 14:33 UTC
    You could use a spyware program like Spector instead of Perl at this stage. It'll capture and dump all sorts of stuff that presumably you can then analyse with Perl. Depends what you are trying to achieve and why. But for the sake of $50 you could maybe save yourself $500 worth of time.