Control and Query Win32 Services at the command line
jdporter
created: 2006-01-11 18:20:10
use Getopt::Long;
use Win32::Service;
use warnings;

# configure the following for the host your services are running on.
my $hostname = ''; # empty string means local host.

my %services;
Win32::Service::GetServices($hostname,\%services);

my %svc = reverse %services; # so that it's keyed by service ID

my %state_code =
(
	1 => 'not running',
	4 => 'started',
	# still need to find out what 2 and 3 mean...
);

sub status
{
	my $func = shift; # 'status'
	for my $svc ( map split(/,/), @_ )
	{
		my %info;
		Win32::Service::GetStatus($hostname,$svc,\%info) or print("Error - No service named '$svc'\n"), next;
		print "Status of $svc:\n";
		$svc{$svc} ne $svc and print "\tDescription: $svc{$svc}\n";
		#printf "\tType: 0x%02X\n", $info{'ServiceType'};
		print "\tState: ", $state_code{$info{'CurrentState'}} || $info{'CurrentState'} , "\n";

		$info{'ProcessId'} and print "\tPID: $info{'ProcessId'}\n";
		#$info{'ControlsAccepted'}

		$info{'Win32ExitCode'} and print
			"\tExited with code $info{'Win32ExitCode'}.\n";
		$info{'ServiceSpecificExitCode'} and print
			"\tExited with error; code $info{'ServiceSpecificExitCode'} was logged.\n";

		$info{'WaitHint'} and print "\tApprox. $info{'WaitHint'} milliseconds until complete.\n";
		$info{'CheckPoint'} and print "\tCheckpoint: $info{'CheckPoint'}\n";

		print "\n";
	}
}

sub list
{
	for my $svc ( sort keys %svc )
	{
		my $descr = $svc{$svc};
		{
			my %info;
			Win32::Service::GetStatus($hostname,$svc,\%info);
			print "(@info{qw( CurrentState CheckPoint WaitHint )}) ";
		}
		print $svc;
		$svc ne $descr and print qq( "$descr");
		print "\n";
	}
}

my %dispatch =
(
	start  => \&Win32::Service::StartService,
	stop   => \&Win32::Service::StopService,
	pause  => \&Win32::Service::PauseService,
	resume => \&Win32::Service::ResumeService,
);

sub simple
{
	my $func = shift;
	for my $svc ( map split(/,/), @_ )
	{
		print "Attempting to $func $svc...\n\t";
		print $dispatch{$func}->($hostname, $svc) ? "Success!\n" : "Failure!\n";
	}
}

GetOptions(
	'list!' => \&list,
	'status|get_status=s' => \&status,
	'start=s'  => \&simple,
	'stop=s'   => \&simple,
	'pause=s'  => \&simple,
	'resume=s' => \&simple,
);
We're building the house of the future together.
Re: Control and Query Win32 Services at the command line
created: 2006-01-12 03:38:08
How nice!

I was going to write something like this today.
Thanks!

greetz, Uksza

Yes, smart people know that fat arrow autoquotes the left argument. But why should you require your code to be maintained by smart people?
Randal L. Schwartz, Perl hacker
Re^2: Control and Query Win32 Services at the command line
created: 2006-01-12 10:13:43

Thanks! That is great information.
In order not to destroy the context of your reply, I've decided to leave my root node unmodified. Hopefully anyone who downloads my code will also integrate your "patch". I certainly have!
Cheers,

We're building the house of the future together.
Re: Control and Query Win32 Services at the command line
created: 2006-01-12 17:05:08
This looks like a rewrite of the NETSVC command from the Win2K resource kit, but it is missing the "remote host" option, that allows you to control services on other machines. Your code appears to prepared to easily include that option too.
NETSVC.exe (Resource Kit)

Command-line Service Controller. Start, Stop and Query services, but does not cover creating or deleting them. 
Although part of the Windows 2000 resource kit - this command runs fine under NT 4.

Syntax
      NETSVC \\server command servicename 

Key
   server        The workstation or server where the service is running

   servicename   The Name of the service, unlike the SC command this will
                 accept either the DisplayName or the service name

   commands:

        /list     Lists installed services. Omit servicename with this command. 
        /query    Query the status of a service. 
        /start    Start the specified service. 
        /stop     Stop the specified service. 
        /pause    Pause the specified service. 
        /continue Restart a paused service. 

Arguments can be specified in any order:

NETSVC /query \\Server299 "DHCP Client"

NETSVC "DHCP Client" \\Server299 /query

     You're just jealous cause the voices are only talking to me.

     No trees were killed in the sending of this message.    However, a large number of electrons were terribly inconvenienced.

Re^2: Control and Query Win32 Services at the command line
created: 2006-01-12 17:13:18

Surely. Of course the same thing could be done using the standard M$ tools.

But: a. this is Perl, which means it's better;-) and b. you can write a whole stop/wait/start or pause/wait/resume script on one line, even for a chain of dependent services. Heck, you could even use it as a "better pause" command. :-)

We're building the house of the future together.

perlmonks.org content © perlmonks.org and jdporter, NetWallah, uksza

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03