The top answer to this question tells me how to stop/start a remote service. Great. Now, all I need is to wait for the actual stop/start to complete. So, what I\'m looking f
I've never actually seen something that does this specifically but it would be quite easy to knock such a utility out in C\C#\VB or any other language that gives easy access to the Service API. Here's a sample of something in C#.
using System;
using System.ComponentModel;
using System.ServiceProcess;
namespace SCSync
{
class Program
{
private const int ERROR_SUCCESS = 0;
private const int ERROR_INVALID_COMMAND_LINE = 1;
private const int ERROR_NO_ACCESS = 2;
private const int ERROR_COMMAND_TIMEOUT = 3;
private const int ERROR_NO_SERVICE = 4;
private const int ERROR_NO_SERVER = 5;
private const int ERROR_INVALID_STATE = 6;
private const int ERROR_UNSPECIFIED = 7;
static int Main(string[] args)
{
if (args.Length < 2 || args.Length > 4)
{
ShowUsage();
return ERROR_INVALID_COMMAND_LINE;
}
string serviceName = args[0];
string command = args[1].ToUpper();
string serverName = ".";
string timeoutString = "30";
int timeout;
if (args.Length > 2)
{
if (args[2].StartsWith(@"\\"))
{
serverName = args[2].Substring(2);
if (args.Length > 3)
{
timeoutString = args[3];
}
}
else
{
timeoutString = args[2];
}
}
if (!int.TryParse(timeoutString, out timeout))
{
Console.WriteLine("Invalid timeout value.\n");
ShowUsage();
return ERROR_INVALID_COMMAND_LINE;
}
try
{
ServiceController sc = new ServiceController(serviceName, serverName);
switch (command)
{
case "START":
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 0, timeout));
break;
case "STOP":
sc.Stop();
sc.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 0, timeout));
break;
case "PAUSE":
sc.Pause();
sc.WaitForStatus(ServiceControllerStatus.Paused, new TimeSpan(0, 0, 0, timeout));
break;
case "CONTINUE":
sc.Continue();
sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 0, timeout));
break;
default:
Console.WriteLine("Invalid command value.\n");
ShowUsage();
return ERROR_INVALID_COMMAND_LINE;
}
}
catch (System.ServiceProcess.TimeoutException)
{
Console.WriteLine("Operation timed out.\n");
return ERROR_COMMAND_TIMEOUT;
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("You are not authorized to perform this action.\n");
return ERROR_NO_ACCESS;
}
catch (InvalidOperationException opEx)
{
Win32Exception winEx = opEx.InnerException as Win32Exception;
if (winEx != null)
{
switch (winEx.NativeErrorCode)
{
case 5: //ERROR_ACCESS_DENIED
Console.WriteLine("You are not authorized to perform this action.\n");
return ERROR_NO_ACCESS;
case 1722: //RPC_S_SERVER_UNAVAILABLE
Console.WriteLine("The server is unavailable or does not exist.\n");
return ERROR_NO_SERVER;
case 1060: //ERROR_SERVICE_DOES_NOT_EXIST
Console.WriteLine("The service does not exist.\n");
return ERROR_NO_SERVICE;
case 1056: //ERROR_SERVICE_ALREADY_RUNNING
Console.WriteLine("The service is already running.\n");
return ERROR_INVALID_STATE;
case 1062: //ERROR_SERVICE_NOT_ACTIVE
Console.WriteLine("The service is not running.\n");
return ERROR_INVALID_STATE;
default:
break;
}
}
Console.WriteLine(opEx.ToString());
return ERROR_UNSPECIFIED;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return ERROR_UNSPECIFIED;
}
return ERROR_SUCCESS;
}
private static void ShowUsage()
{
Console.WriteLine("SCSync usage:\n");
Console.WriteLine("SCSync.exe service command \n");
Console.WriteLine(" service The name of the service upon which the command will act. (Required)");
Console.WriteLine(" command The command to execute - one of: start|stop|pause|continue. (Required)");
Console.WriteLine(" server The name of the server on which the target service runs. This must start with \\. (Optional)");
Console.WriteLine(" timeout The timeout period in seconds in which the command should finish. The default is 30 seconds. (Optional)");
Console.WriteLine("\n");
}
}
}
The WaitForStatus is just a polling loop and could be easily replaced in any other language. The rest is just OpenService and ControlService.