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

В верхнем ответе на этот вопрос рассказывается, как остановить / запустить удаленный сервис. Отлично. Теперь все, что мне нужно, это дождаться фактической остановки / начала, чтобы завершить. Итак, я ищу команду dos:

  1. Запуск службы, должен возвращаться только после запуска службы (или после тайм-аута, повышения уровня ошибки)
  2. Остановить службу, вернуться только после остановки службы

Ответы [ 10 ]

115 голосов
/ 12 июня 2010

Я создал набор пакетных сценариев, которые используют 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
10 голосов
/ 13 апреля 2011

А как насчет powershell и WaitForStatus? Например, приведенный ниже скрипт перезапустит SQL Server на удаленной машине:

$computer = "COMPUTER_NAME"
$me = new-object -typename System.Management.Automation.PSCredential -argumentlist "DOMAIN\user", (convertto-securestring "password" -asplaintext -force)
$restartSqlServer = { 
    $sqlServer = get-service mssqlserver
    $waitInterval = new-timespan -seconds 5
    if (-not ($sqlServer.Status -eq "Stopped")) {
        $sqlServer.Stop()
        $sqlServer.WaitForStatus('Stopped', $waitInterval) 
    }
    $sqlServer.Start()
    $sqlServer.WaitForStatus('Running', $waitInterval) 
}     
icm -ComputerName $computer -ScriptBlock $restartSqlServer -Credential $me 
8 голосов
/ 16 сентября 2009

Я никогда не видел чего-то такого, что делает это специально, но было бы довольно легко вывести такую ​​утилиту из C \ C # \ VB или любого другого языка, который предоставляет легкий доступ к Service 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.

6 голосов
/ 18 января 2013

Решение Эрика Фальскена работает отлично. +1.

Но я хотел бы добавить, что команда timeout иногда завершается ошибкой: «Перенаправление ввода не поддерживается, выход из процесса немедленно»

Чтобы это исправить, мне пришлось заменить команду timeout:

timeout /t 2 /nobreak >NUL

со следующим:

ping -n 2 127.0.0.1  1>NUL
5 голосов
/ 19 октября 2011

Редактировать 20.10.2011 - обновил мой код. Я отправил это прежде, чем полностью отладить. Большое спасибо Эрику Фальскену. Какое отличное решение. Я подправил код Эрика (кстати, поищите пару опечаток, если вы намереваетесь его использовать). Я добавил ведение журнала и дополнительную проверку ошибок для некоторых условий, которые Эрик не учел. Поскольку меня больше всего интересует перезапуск службы (а не просто остановка и / или запуск), я опирался только на код перезапуска Эрика. В любом случае, я выкладываю свою версию, надеюсь, вам понравится!

@ECHO off
:: This script originally authored by Eric Falsken http://stackoverflow.com/
:: Revised for by George Perkins 10/20/2011
IF [%1]==[] GOTO Usage
IF [%2]==[] GOTO Usage

:SetLocalVariables
SET /A MyDelay=0 
SET MyHours=%time:~0,2%
IF %MyHours%==0 SET MyHours=00
IF %MyHours%==1 SET MyHours=01
IF %MyHours%==2 SET MyHours=02
IF %MyHours%==3 SET MyHours=03
IF %MyHours%==4 SET MyHours=04
IF %MyHours%==5 SET MyHours=05
IF %MyHours%==6 SET MyHours=06
IF %MyHours%==7 SET MyHours=07
IF %MyHours%==8 SET MyHours=08
IF %MyHours%==9 SET MyHours=09
SET MyMinutes=%time:~3,2%
SET MySeconds=%time:~6,2%
SET MyHundredths=%time:~9,2%
SET MyMonth=%date:~4,2%
SET MyDay=%date:~-7,2%
SET MyCentury=%date:~-4,4%
SET MyTimeStamp=%MyCentury%%MyMonth%%MyDay%%MyHours%%MyMinutes%%MySeconds%
IF "%3" == "" (
         SET MyLog=C:\Temp
   ) ELSE (
         SET MyLog=%3
   ) 
SET MyLogFile=%MyLog%\ServiceRestart%MyTimeStamp%.log
ECHO.
ECHO. >> %MyLogFile%
ECHO ------------- ------------- %MyHours%:%MyMinutes%:%MySeconds%.%MyHundredths% %MyMonth%/%MyDay%/%MyCentury% ------------- ------------- 
ECHO ------------- ------------- %MyHours%:%MyMinutes%:%MySeconds%.%MyHundredths% %MyMonth%/%MyDay%/%MyCentury% ------------- ------------- >> %MyLogFile% 
ECHO Begin batch program %0. 
ECHO Begin batch program %0. >> %MyLogFile%
ECHO Logging to file %MyLogFile%. 
ECHO Logging to file %MyLogFile%. >> %MyLogFile% 
ECHO Attempting to restart service %2 on computer %1.
ECHO Attempting to restart service %2 on computer %1. >> %MyLogFile%

PING -n 1 %1 | FIND "TTL=" >> %MyLogFile%
IF errorlevel 1 IF NOT errorlevel 2 GOTO SystemOffline
SC \\%1 query %2 | FIND "FAILED 1060" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO InvalidServiceName
SC \\%1 query %2 | FIND "STATE" >> %MyLogFile%
IF errorlevel 1 IF NOT errorlevel 2 GOTO SystemOffline

:ResolveInitialState
SET /A MyDelay+=1
SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO StopService
SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO StartService
SC \\%1 query %2 | FIND "STATE" | FIND "PAUSED" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO SystemOffline
ECHO Service State is changing, waiting %MyDelay% seconds for service to resolve its state before making changes.
ECHO Service State is changing, waiting %MyDelay% seconds for service to resolve its state before making changes. >> %MyLogFile%
TIMEOUT /t %MyDelay% /nobreak >> %MyLogFile%
GOTO ResolveInitialState

:StopService
SET /A MyDelay=0
ECHO Stopping %2 on \\%1.
ECHO Stopping %2 on \\%1. >> %MyLogFile%
SC \\%1 stop %2 | FIND "FAILED" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO Unstoppable

:StoppingServiceDelay
SET /A MyDelay+=1
IF %MyDelay%==21 GOTO MaybeUnStoppable
ECHO Waiting %MyDelay% seconds for %2 to stop.
ECHO Waiting %MyDelay% seconds for %2 to stop. >> %MyLogFile%
TIMEOUT /t %MyDelay% /nobreak >> %MyLogFile%
:StoppingService
SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO StoppedService
SC \\%1 query %2 | FIND "STATE" | FIND "STOP_PENDING" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO StoppingServiceDelay
GOTO StoppingServiceDelay

:MaybeUnStoppable
:: If we got here we waited approximately 3 mintues and the service has not stopped.
SC \\%1 query %2 | FIND "NOT_STOPPABLE" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO OneLastChance
GOTO Unstoppable 

:OneLastChance
SC \\%1 stop %2 >> %MyLogFile%
SET /A MyDelay+=1
ECHO Waiting %MyDelay% seconds for %2 to stop.
ECHO Waiting %MyDelay% seconds for %2 to stop. >> %MyLogFile%
TIMEOUT /t %MyDelay% /nobreak >> %MyLogFile%
SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO StoppedService
SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >> %MyLogFile%
IF errorlevel 1 IF NOT errorlevel 2 GOTO UnknownState
SC \\%1 query %2 | FIND "NOT_STOPPABLE" >> %MyLogFile%
IF errorlevel 0 IF NOT errorlevel 1 GOTO Unstoppable
GOTO StoppingServiceDelay

:StoppedService
ECHO %2 on \\%1 is stopped.
ECHO %2 on \\%1 is stopped. >> %MyLogFile%
GOTO StartService

:StartService
SET /A MyDelay=0 
ECHO Starting %2 on \\%1.
ECHO Starting %2 on \\%1. >> %MyLogFile%
SC \\%1 start %2 >> %MyLogFile%

GOTO StartingService
:StartingServiceDelay
SET /A MyDelay+=1
ECHO Waiting %MyDelay% seconds for %2 to start.
ECHO Waiting %MyDelay% seconds for %2 to start. >> %MyLogFile%
TIMEOUT /t %MyDelay% /nobreak >> %MyLogFile%
:StartingService
SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >> %MyLogFile%
IF errorlevel 1 IF NOT errorlevel 2 GOTO StartingServiceDelay

:StartedService
ECHO %2 on \\%1 is started.
ECHO %2 on \\%1 is started. >> %MyLogFile%
GOTO EndExit

:SystemOffline
ECHO Failure! Server \\%1 or service %2 is not accessible or is offline!
ECHO Failure! Server \\%1 or service %2 is not accessible or is offline! >> %MyLogFile%
ECHO See log file %MyLogFile% for details!
GOTO EndExit

:InvalidServiceName
ECHO Failure! Service %2 is not valid!
ECHO Failure! Service %2 is not valid! >> %MyLogFile%
ECHO See log file %MyLogFile% for details!
GOTO EndExit

:UnknownState
ECHO Failure! Service %2 in an unknown state and cannot be stopped!
ECHO Failure! Service %2 in an unknown state and cannot be stopped! >> %MyLogFile%
ECHO See log file %MyLogFile% for details!
GOTO EndExit

:UnStoppable
ECHO Failure! Service %2 cannot be stopped! Check dependencies or system state.
ECHO Failure! Service %2 cannot be stopped! Check dependencies or system state. >> %MyLogFile%
ECHO See log file %MyLogFile% for details!
GOTO EndExit

:Usage
ECHO Will restart a remote service, waiting for the service to stop/start (if necessary).
ECHO.
ECHO Usage:
ECHO %0 [system name] [service name] [logfile path]
ECHO Example: %0 server1 MyService C:\Temp\Log
ECHO.
GOTO EndExit

:EndExit
ECHO.
ECHO %0 Ended.
ECHO.
4 голосов
/ 18 марта 2014

А как насчет PowerShell и Командлет Restart-Service ? :)

Get-Service W3SVC -computer myserver | Restart-Service
2 голосов
/ 23 февраля 2015

Я улучшил сценарий Эрика Фальскена и пересмотрел Джерордж Перкинс.

Изменения:

  • теперь это не только скрипт перезапуска. Сценарий может запускать, останавливать и перезапускать локальную или удаленную службу;
  • удалено ведение журнала (если вы хотите это, вы можете использовать его, просто запустив SCRIPT_NAME.bat> logfile.txt);
  • редких оптимизаций.

    @ECHO off
    :: This script originally authored by Eric Falsken http://stackoverflow.com/
    :: Revised by George Perkins 10/20/2011
    :: Revised by Armando Contestabile 02/23/2015
    IF "%1"=="" GOTO Usage
    IF "%2"=="" GOTO Usage
    
    SET ACTION=%1
    SET SERVICENAME=%2
    
    IF "%3"=="" (
        SET SYSTEMNAME=%COMPUTERNAME%
    ) ELSE (
        SET SYSTEMNAME=%3
    )
    
    IF "%ACTION%" == "stop" (
        SET ACTION=STOP
    ) ELSE IF "%ACTION%" == "STOP" (
        SET ACTION=STOP
    ) ELSE IF "%ACTION%" == "start" (
        SET ACTION=START
    ) ELSE IF "%ACTION%" == "START" (
        SET ACTION=START
    ) ELSE IF "%ACTION%" == "restart" (
        SET ACTION=RESTART
    ) ELSE IF "%ACTION%" == "RESTART" (
        SET ACTION=RESTART
    ) ELSE GOTO Usage
    
    SET STATE=
    SET CURRENT_STATUS=
    SET /A DEFAULT_DELAY=5
    SET /A SLEEP_COUNT=0
    SET /A RESTARTED=0
    SET /A MAX_WAIT_PERIODS=5
    
    ECHO.
    ECHO Attempting to %ACTION% service %SERVICENAME% on computer %SYSTEMNAME%.
    
    PING -n 1 %SYSTEMNAME% | FIND "TTL=" >nul 2>&1
    IF ERRORLEVEL 1 IF NOT ERRORLEVEL 2 (
        ECHO Failure! Server \\%SYSTEMNAME% or service %SERVICENAME% is not accessible or is offline!
        EXIT /B 1
    )
    SC \\%SYSTEMNAME% query %SERVICENAME% | FIND "FAILED 1060" >nul 2>&1
    IF ERRORLEVEL 0 IF NOT ERRORLEVEL 1 (
        ECHO Failure! Service %SERVICENAME% is not valid!
        EXIT /B 2
    )
    SC \\%SYSTEMNAME% query %SERVICENAME% | FIND "STATE" >nul 2>&1
    IF ERRORLEVEL 1 IF NOT ERRORLEVEL 2 (
        ECHO Failure! Server \\%SYSTEMNAME% or service %SERVICENAME% is not accessible or is offline!
        EXIT /B 3
    )
    
    :Dispatch
    FOR /f "tokens=*" %%i IN ('SC \\%SYSTEMNAME% query %SERVICENAME% ^| FIND "STATE"') DO SET STATE=%%i
    
    ECHO %STATE% | FINDSTR /C:"1" >nul
    IF %ERRORLEVEL%==0 SET CURRENT_STATUS=STOPPED
    ECHO %STATE% | FINDSTR /C:"2" >nul
    IF %ERRORLEVEL%==0 SET CURRENT_STATUS=START_PENDING
    ECHO %STATE% | FINDSTR /C:"3" >nul
    IF %ERRORLEVEL%==0 SET CURRENT_STATUS=STOP_PENDING
    ECHO %STATE% | FINDSTR /C:"4" >nul
    IF %ERRORLEVEL%==0 SET CURRENT_STATUS=RUNNING
    ECHO %STATE% | FINDSTR /C:"5" >nul
    IF %ERRORLEVEL%==0 SET CURRENT_STATUS=CONTINUE_PENDING
    ECHO %STATE% | FINDSTR /C:"6" >nul
    IF %ERRORLEVEL%==0 SET CURRENT_STATUS=PAUSE_PENDING
    ECHO %STATE% | FINDSTR /C:"7" >nul
    IF %ERRORLEVEL%==0 SET CURRENT_STATUS=PAUSED
    
    ECHO Current status of service is %CURRENT_STATUS%
    
    IF NOT "%CURRENT_STATUS%"=="RUNNING" IF NOT "%CURRENT_STATUS%"=="STOPPED" IF NOT "%CURRENT_STATUS%"=="PAUSED" (
        IF "%SLEEP_COUNT%"=="%MAX_WAIT_PERIODS%" (
            ECHO Service state won't change. Script exececution is canceled.
            EXIT /B 4
        )
        ECHO Service State is changing, waiting %DEFAULT_DELAY% seconds...
        SLEEP %DEFAULT_DELAY%
        SET /A SLEEP_COUNT+=1
        GOTO Dispatch
    )
    
    IF "%ACTION%"=="START" (
        IF "%CURRENT_STATUS%"=="RUNNING" (
            ECHO Service %SERVICENAME% is running.
            GOTO EndExit
        ) ELSE (
            GOTO StartService
        )
    ) ELSE IF "%ACTION%"=="RESTART" (
        IF "%CURRENT_STATUS%"=="RUNNING" (
            IF %RESTARTED%==1 (
                ECHO Service %SERVICENAME% restarted.
                GOTO EndExit
            )
            SET /A SLEEP_COUNT=0
            GOTO StopService
        ) ELSE (
            SET /A RESTARTED=1
            GOTO StartService
        )
    ) ELSE IF "%ACTION%"=="STOP" (
        IF "%CURRENT_STATUS%"=="STOPPED"  (
            ECHO Service %SERVICENAME% is stopped.
            GOTO EndExit
        ) ELSE (
            GOTO StopService
        )
    )
    
    :StartService
    ECHO Starting %SERVICENAME% on \\%SYSTEMNAME%
    SC \\%SYSTEMNAME% start %SERVICENAME% >nul 2>&1
    SET SLEEP_COUNT=0
    GOTO Dispatch
    
    :StopService
    ECHO Stopping %SERVICENAME% on \\%SYSTEMNAME%
    SC \\%SYSTEMNAME% stop %SERVICENAME% >nul 2>&1
    SET SLEEP_COUNT=0
    GOTO Dispatch
    
    :Usage
    ECHO This script can start/stop/restart a local or remote service, waiting for the service to stop/start ^(if necessary^).
    ECHO.
    ECHO Usage:
    ECHO %0 ^<start^|stop^|restart^> ^<SERVICE^> [SYSTEM]
    ECHO.
    ECHO If no SYSTEM is provided, the script attempts to execute on the local system.
    EXIT /B 5
    
    :EndExit
    ECHO.
    EXIT /B 0
    
2 голосов
/ 26 августа 2010

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

0 голосов
/ 10 сентября 2009

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

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

0 голосов
/ 10 сентября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...