Stopping/Starting a remote Windows service and waiting for it to open/close

后端 未结 11 1504
广开言路
广开言路 2020-12-02 06:42

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

11条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-02 07:20

    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.

提交回复
热议问题