Остановка/Запуск удаленной службы Windows и ожидание его для открытий/закрытия

В дополнение к упомянутым примерам введите псевдонимы (а не псевдонимы пространства имен) может быть удобным при повторном обращении к универсальным типам:

Dictionary<string, SomeClassWithALongName> foo = new Dictionary<string, SomeClassWithALongName>();

private void DoStuff(Dictionary<string, SomeClassWithALongName> dict) {}

По сравнению с:

using FooDict = Dictionary<string, SomeClassWithALongName>;

FooDict foo = new FooDict();

private void DoStuff(FooDict dict) {}
66
задан Community 23 May 2017 в 12:00
поделиться

5 ответов

Я создал набор пакетных сценариев, в которых для этого используется sc.exe. Они прикреплены ниже. Для запуска этих сценариев вы должны быть пользователем с правами администратора на целевой машине и запускать его с компьютера, который является членом того же домена . Его можно настроить так, чтобы он мог работать извне домена (например, из VPN), но существует множество уровней безопасности для работы, включая межсетевые экраны, DCOM и учетные данные безопасности.

На днях я собираюсь придумать эквивалент PowerShell, что должно быть намного проще.

safeServiceStart.bat

@echo off
:: This script originally authored by Eric Falsken

IF [%1]==[] GOTO usage
IF [%2]==[] GOTO usage

ping -n 1 %1 | FIND "TTL=" >NUL
IF errorlevel 1 GOTO SystemOffline
SC \\%1 query %2 | FIND "STATE" >NUL
IF errorlevel 1 GOTO SystemOffline

:ResolveInitialState
SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >NUL
IF errorlevel 0 IF NOT errorlevel 1 GOTO StartService
SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >NUL
IF errorlevel 0 IF NOT errorlevel 1 GOTO StartedService
SC \\%1 query %2 | FIND "STATE" | FIND "PAUSED" >NUL
IF errorlevel 0 IF NOT errorlevel 1 GOTO SystemOffline
echo Service State is changing, waiting for service to resolve its state before making changes
sc \\%1 query %2 | Find "STATE"
timeout /t 2 /nobreak >NUL
GOTO ResolveInitialState

:StartService
echo Starting %2 on \\%1
sc \\%1 start %2 >NUL

GOTO StartingService
:StartingServiceDelay
echo Waiting for %2 to start
timeout /t 2 /nobreak >NUL
:StartingService
SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >NUL
IF errorlevel 1 GOTO StartingServiceDelay

:StartedService
echo %2 on \\%1 is started
GOTO:eof

:SystemOffline
echo Server \\%1 is not accessible or is offline
GOTO:eof

:usage
echo %0 [system name] [service name]
echo Example: %0 server1 MyService
echo.
GOTO:eof

safeServiceStop.bat

@echo off
:: This script originally authored by Eric Falsken

IF [%1]==[] GOTO usage
IF [%2]==[] GOTO usage

ping -n 1 %1 | FIND "TTL=" >NUL
IF errorlevel 1 GOTO SystemOffline
SC \\%1 query %2 | FIND "STATE" >NUL
IF errorlevel 1 GOTO SystemOffline

:ResolveInitialState
SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >NUL
IF errorlevel 0 IF NOT errorlevel 1 GOTO StopService
SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >NUL
IF errorlevel 0 IF NOT errorlevel 1 GOTO StopedService
SC \\%1 query %2 | FIND "STATE" | FIND "PAUSED" >NUL
IF errorlevel 0 IF NOT errorlevel 1 GOTO SystemOffline
echo Service State is changing, waiting for service to resolve its state before making changes
sc \\%1 query %2 | Find "STATE"
timeout /t 2 /nobreak >NUL
GOTO ResolveInitialState

:StopService
echo Stopping %2 on \\%1
sc \\%1 stop %2 %3 >NUL

GOTO StopingService
:StopingServiceDelay
echo Waiting for %2 to stop
timeout /t 2 /nobreak >NUL
:StopingService
SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >NUL
IF errorlevel 1 GOTO StopingServiceDelay

:StopedService
echo %2 on \\%1 is stopped
GOTO:eof

:SystemOffline
echo Server \\%1 or service %2 is not accessible or is offline
GOTO:eof

:usage
echo Will cause a remote service to STOP (if not already stopped).
echo This script will waiting for the service to enter the stopped state if necessary.
echo.
echo %0 [system name] [service name] {reason}
echo Example: %0 server1 MyService
echo.
echo For reason codes, run "sc stop"
GOTO:eof

safeServiceRestart.bat

@echo off
:: This script originally authored by Eric Falsken

if [%1]==[] GOTO usage
if [%2]==[] GOTO usage

ping -n 1 %1 | FIND "TTL=" >NUL
IF errorlevel 1 GOTO SystemOffline
SC \\%1 query %2 | FIND "STATE" >NUL
IF errorlevel 1 GOTO SystemOffline

:ResolveInitialState
SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >NUL
IF errorlevel 0 IF NOT errorlevel 1 GOTO StopService
SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >NUL
IF errorlevel 0 IF NOT errorlevel 1 GOTO StartService
SC \\%1 query %2 | FIND "STATE" | FIND "PAUSED" >NUL
IF errorlevel 0 IF NOT errorlevel 1 GOTO SystemOffline
echo Service State is changing, waiting for service to resolve its state before making changes
sc \\%1 query %2 | Find "STATE"
timeout /t 2 /nobreak >NUL
GOTO ResolveInitialState

:StopService
echo Stopping %2 on \\%1
sc \\%1 stop %2 %3 >NUL

GOTO StopingService
:StopingServiceDelay
echo Waiting for %2 to stop
timeout /t 2 /nobreak >NUL
:StopingService
SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >NUL
IF errorlevel 1 GOTO StopingServiceDelay

:StopedService
echo %2 on \\%1 is stopped
GOTO StartService

:StartService
echo Starting %2 on \\%1
sc \\%1 start %2 >NUL

GOTO StartingService
:StartingServiceDelay
echo Waiting for %2 to start
timeout /t 2 /nobreak >NUL
:StartingService
SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >NUL
IF errorlevel 1 GOTO StartingServiceDelay

:StartedService
echo %2 on \\%1 is started
GOTO:eof

:SystemOffline
echo Server \\%1 or service %2 is not accessible or is offline
GOTO:eof

:usage
echo Will restart a remote service, waiting for the service to stop/start (if necessary)
echo.
echo %0 [system name] [service name] {reason}
echo Example: %0 server1 MyService
echo.
echo For reason codes, run "sc stop"
GOTO:eof
117
ответ дан 24 November 2019 в 14:55
поделиться

NET START и NET STOP не должны возвращаться, пока служба не сообщит, что служба запущена или остановлен успешно.

0
ответ дан 24 November 2019 в 14:55
поделиться

Я не верю, что вы можете сделать это с помощью простой команды dos. Вы можете проверить Code Project или другие подобные сайты, чтобы узнать, есть ли уже какое-то специальное решение для этого.

Если нет, вы можете написать вторичную службу Windows, которая сделает это за вас, выставив запуск / остановку функциональность через конечную точку WCF. Для удаленного доступа к этой вторичной службе вы можете написать простое консольное приложение, которое подключается к этой службе для запуска / остановки рассматриваемой службы Windows. Поскольку это консольное приложение, оно имитирует желаемое поведение при работе из командной строки и не возвращается до завершения (или возникновения ошибки). Это не то простое и понятное решение, которое вы ищете, но я

-1
ответ дан 24 November 2019 в 14:55
поделиться

На самом деле я никогда не видел чего-то, что делает это специально, но было бы довольно легко выбить такую ​​утилиту в C \ C # \ VB или любом другом языке, который дает легкий доступ к Сервису API. Вот пример того, что написано на 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 <server> <timeout>\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");
        }
    }
}

WaitForStatus - это просто цикл опроса, и его можно легко заменить на любом другом языке. Остальное - это просто OpenService и ControlService.

8
ответ дан 24 November 2019 в 14:55
поделиться

Сценарии Эрика Фальскена отлично подходят для этой цели. Но обратите внимание, что они используют команду timeout, которая доступна только в Vista/Server2003 и новее. Для компьютера с XP вы можете вместо этого использовать sleep.exe из комплекта ресурсов NT. (Это должен быть комментарий к ответу Эрика, но для этого недостаточно представителей).

2
ответ дан 24 November 2019 в 14:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: