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";
}
}