어떻게 Windows 서비스가 프로그래밍 방식으로 다시 시작될 수 있습니까?


답변:


187

실패 후 서비스를 다시 시작하도록 설정하십시오 (제어판에서 서비스를 두 번 클릭하고 해당 탭을 살펴보십시오. 이름을 잊어 버렸습니다). 그런 다음 서비스를 다시 시작하려면 언제든지 전화하십시오 Environment.Exit(1)(또는 0이 아닌 반환) .OS가 서비스를 다시 시작합니다.


7
위치가 서비스 패널에 있으면 해당 서비스를 마우스 오른쪽 버튼으로 클릭하고 속성을 선택한 다음 복구 탭을 선택하십시오.
제임스 마이클 헤어

20
이것이 원하는 동작을 달성하는 방법을 알지만 리턴 코드 1은 시스템에 오류가 있음을 알리기위한 것입니다. 실제로 오류가없고 서비스를 다시 시작하려는 경우이 나쁜 습관이 아닙니까?
mgttlinger

4
설치 후 이벤트에서 서비스 설치 프로그램이 프로그래밍 방식으로 수행 할 수 있습니다. 클릭하지 않아도됩니다. 서비스가 원격 서버에 있고 테스트와 같이 하루에 여러 번 설치해야하는 경우는 어떻게됩니까?
Dean Kuga

5
@ mgttlinger : 예, 서비스가 건강 할 때 나쁜 습관이므로 다시 시작할 필요가 없습니다. 그러나 일부 서비스 아키텍처는 우리의 범위를 벗어 났으며 다시 시작 해야하는 경우 좋지 않은 증상이므로 가능한 한 최소한의 복원을 닫고 해제하고 '발을 자르는'문제는 없습니다. 서비스가 잘못 실행되면 상황이 악화 될 수 있습니다 (불필요).
Luciano

5
@JohnLeidegren 올바른 종료를 원하면 서비스 복구 설정 화면에서 '오류로 인한 중지 작업 활성화'확인란을 활성화하여 설정 한 Service.ExitCode = 1다음 실행할 Service.Stop()수 있습니다. 이 방법을 사용하면 올바른 종료가 가능하고 다시 시작이 트리거됩니다.
Chris Rice

22
Dim proc As New Process()
Dim psi As New ProcessStartInfo()

psi.CreateNoWindow = True
psi.FileName = "cmd.exe"
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE"
psi.LoadUserProfile = False
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Hidden
proc.StartInfo = psi
proc.Start()

3
공백이 있으면 ""arround 서비스 이름을 추가하십시오.
apc

4
이것은 권한있는 계정으로 실행되는 서비스에만 해당되며 어쨌든 나쁜 생각입니다.
Dmitry Gusarov

17

서비스를 실행중인 사용자 계정에 서비스를 중지했다가 다시 시작할 수있는 권한이 있는지도 확신 할 수 없습니다.


sc1.exe를 볼 때 +1 버전이지만 sc.exe를 볼 때 OpenSCManager ()를 호출 할 때 SERVICE_QUERY_CONFIG를 dwDesiredAccess로 사용하고 SERVICE_START | SERVICE_STOP하여 특정 서비스를 열고 정상적으로 작동합니다 (액세스에 문제 없음). .NET에서 어떻게 할 수 있는지 잘 모르겠습니다.
n0p

대부분의 Windows 서비스는 시스템으로 실행되므로 문제가되지 않습니다.
스위치

@ 스위치 NETWORK SERVICE 하에서 실행되는 방대한 서비스가 있으며 기본적으로 자체 실행 파일을 열 권한도 없습니다.
AgentFire 2012 년

@AgentFire는 정확하지만 기본값은 네트워크 서비스가 아닌 로컬 시스템입니다. 로컬 시스템에는 기본적으로 운영 체제에 대한 최고 수준의 권한이 있으며 로컬 관리자 그룹 구성원에게 할당 된 권한을 초과합니다.
전환

@ 스위치이지만 가장 많은 권한을 사용하는 것은 PoL 원칙을 위반하는 것 입니다.
AgentFire

12

스스로 재시작하는 DOS 명령 프롬프트 인 프로세스를 작성할 수 있습니다.

 Process process = new Process();
 process.StartInfo.FileName = "cmd";
 process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
 process.Start();

이것은 다른 작업을 수행하지 않고도 호출 스레드의 보안 컨텍스트를 상속합니다. 다시 시작하기에 충분한 마력이있는 한 좋습니다.
Clay

12
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);

where SERVICENAME서비스 이름입니다 (서비스 이름의 공백을 설명하기 위해 큰 따옴표 포함, 그렇지 않으면 생략 할 수 있음).

깨끗하고 자동 재시작 구성이 필요하지 않습니다.


9
& vs &&에 대해 새로운 것을 배웠습니다. [command1] & [command2]는 항상 두 명령을 순차적으로 실행하지만 [command1] && [command2]는 command1이 성공적으로 실행되는 경우에만 command2를 실행합니다 ( autoitscript.com/forum/topic/… )
Jeffrey 기사

5

자체 재시작 이유에 따라 다릅니다.

서비스를 주기적으로 정리하는 방법을 찾고 있다면 주기적으로 제거 루틴을 발생시키는 타이머가 서비스에서 실행될 수 있습니다.

장애 발생시 다시 시작하는 방법을 찾고 있다면 서비스 호스트 자체가 설정시 해당 기능을 제공 할 수 있습니다.

왜 서버를 다시 시작해야합니까? 당신은 무엇을 달성하려고합니까?


1
Large Object Heap 및 메모리 조각화가 염려되면 작동하지 않습니다. 아마도 .NET 4 / 4.5 및 64 비트 프로세스가이 작업에 많은 도움이되었습니다.
David Kassa

3

나는 당신이 독립적 인 서비스를 할 수 있다고 생각하지 않습니다 (Restart를 호출하면 서비스가 중지되어 다시 시작 명령이 중단되고 다시 시작되지 않습니다). 두 번째 .exe (ServiceManager 클래스를 사용하는 콘솔 앱)를 추가 할 수 있으면 독립형 .exe를 시작하고 서비스를 다시 시작한 다음 종료 할 수 있습니다.

다시 생각하면, 서비스를 시작하기 위해 서비스가 예약 된 작업 (예 : 명령 줄 'at'명령을 사용하여)을 등록한 다음 스스로 중지하도록 할 수 있습니다. 아마도 효과가있을 것입니다.


3

배치 파일 또는 EXE로 셸을 만들 때 문제는 서비스에 외부 앱을 실행하는 데 필요한 권한이 있거나 없을 수 있다는 것입니다.

내가 찾은 가장 깨끗한 방법은 서비스 제어 관리자의 진입 점 인 OnStop () 메서드를 사용하는 것입니다. 그런 다음 모든 정리 코드가 실행되고 중지 코드가 작동한다고 가정하면 정지 소켓이나 다른 프로세스가 없습니다.

이렇게하려면 OnStop 메소드가 오류 코드와 함께 종료하도록 지시하는 플래그를 설정해야합니다. 그런 다음 SCM은 서비스를 다시 시작해야한다는 것을 알고 있습니다. 이 플래그가 없으면 SCM에서 서비스를 수동으로 중지 할 수 없습니다. 또한 오류가 발생하면 서비스를 다시 시작하도록 설정했다고 가정합니다.

내 정지 코드는 다음과 같습니다.

...

bool ABORT;

protected override void OnStop()
{
    Logger.log("Stopping service");
    WorkThreadRun = false;
    WorkThread.Join();
    Logger.stop();
    // if there was a problem, set an exit error code
    // so the service manager will restart this
    if(ABORT)Environment.Exit(1);
}

서비스에 문제가 발생하여 다시 시작해야하는 경우 SCM에서 서비스를 중지시키는 스레드를 시작합니다. 이를 통해 서비스 자체를 정리할 수 있습니다.

...

if(NeedToRestart)
{
    ABORT = true;
    new Thread(RestartThread).Start();
}

void RestartThread()
{
    ServiceController sc = new ServiceController(ServiceName);
    try
    {
        sc.Stop();
    }
    catch (Exception) { }
}

2

Windows 스케줄러를 사용하여 서비스 다시 시작을 예약합니다. 문제는 자신을 다시 시작할 수 없지만 스스로 중지 할 수 있다는 것입니다. (당신은 본질적으로 앉아있는 지점을 톱질했습니다 ... 비유를 얻는다면) 별도의 프로세스가 필요합니다. Windows 스케줄러가 적합합니다. 서비스 자체 내에서도 서비스를 다시 시작하여 일회성 작업을 즉시 실행하도록 예약하십시오.

그렇지 않으면, 당신을 위해 그것을하는 "목자"프로세스를 만들어야합니다.


2

이 질문에 대한 첫 번째 대답은 가장 간단한 해결책입니다. "Environment.Exit (1)"Windows Server 2008 R2에서 이것을 사용하고 있으며 완벽하게 작동합니다. 서비스 자체가 중지되고 O / S가 1 분 동안 기다렸다가 다시 시작됩니다.


대기 시간은 대기하도록 설정 한 시간에 따라 다릅니다. 그러나 기본값은 1 분이지만 누군가가 원하지 않으면 대답이 잘못된 인상을 줄 것입니다.
Espen

1

나는 그것이 할 수 있다고 생각하지 않습니다. 서비스가 "중지"되면 완전히 언로드됩니다.

글쎄, 항상, 내가 생각하는 방법이 있습니다. 예를 들어, 분리 된 프로세스를 작성하여 서비스를 중지 한 다음 다시 시작한 다음 종료 할 수 있습니다.


0

더 나은 방법은 NT 서비스를 응용 프로그램의 래퍼로 사용하는 것입니다. NT 서비스가 시작되면 응용 프로그램은 "유휴"모드에서 시작하여 명령이 시작되기를 기다리거나 자동으로 시작되도록 구성 할 수 있습니다.

자동차가 시동되면 유휴 상태에서 시작하여 명령이 전진 또는 후진 될 때까지 기다립니다. 또한 응용 프로그램 노출 방법을 선택할 수있는 원격 관리 향상과 같은 다른 이점도 있습니다.


0

그냥 전달 : 그리고 추가 정보를 추가 할 것이라고 생각했습니다 ...

또한 예외를 던질 수 있습니다. 그러면 Windows 서비스가 자동으로 닫히고 자동 다시 시작 옵션이 시작됩니다.이 문제의 유일한 문제는 PC에 개발 환경이 있으면 JIT가 시작하려고한다는 것입니다. 디버그 Y / N이라는 메시지가 나타납니다. 아니오라고 말하면 닫히고 올바르게 다시 시작됩니다. (JIT가없는 PC에서는 모두 작동합니다). im trolling 이유는이 JIT가 Win 7 (XP 등에서 잘 작동하는 데 익숙 함)에 새로 도입되었고 JIT를 비활성화하는 방법을 찾으려고 노력하고 있기 때문입니다 .... 나는 여기에 언급 된 Environment.Exit 방법을 시도 할 수 있습니다. 그것도 작동합니다.

크리스티안 : 브리스톨, 영국


3
이러한 예외 예외, exit (1) 솔루션은 모두 응용 프로그램의 적절한 정리를 피합니다. 우아하게 종료하는 것은 좋지 않은 해결책입니다
devshorts

0

다음과 같이 restart.bat 파일을 작성하십시오.

@echo on
set once="C:\Program Files\MyService\once.bat"
set taskname=Restart_MyService
set service=MyService
echo rem %time% >%once%
echo net stop %service% >>%once%
echo net start %service% >>%once%
echo del %once% >>%once%

schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z
schtasks /run /tn %taskname%

그런 다음 % service %가 시작될 때 % taskname % 작업을 삭제하십시오.


0

응용 프로그램 코드를 호스팅 할 별도의 appdomain을 만듭니다. 다시 시작해야하는 경우 프로세스 (Windows 서비스) 대신 앱 도메인을 언로드했다가 다시로드 할 수 있습니다. 이것은 IIS 응용 프로그램 풀이 작동하는 방식이며, asp.net 응용 프로그램을 직접 실행하지 않으며 별도의 appdmain을 사용합니다.


-2

가장 쉬운 방법은 다음과 같은 배치 파일을 갖는 것입니다.

순 정지 순 시작

원하는 시간 간격으로 스케줄러에 파일을 추가하십시오.


배치가 두 명령 사이에서 중지 되었기 때문에 작동하지 않습니다. 서비스 자체의 하위 프로세스이기 때문입니다.
Orabîg

-3
private static void  RestartService(string serviceName)
    {
        using (var controller = new ServiceController(serviceName))
        {
            controller.Stop();
            int counter = 0;
            while (controller.Status != ServiceControllerStatus.Stopped)
            {
                Thread.Sleep(100);
                controller.Refresh();
                counter++;
                if (counter > 1000)
                {
                    throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName));
                }
            }

            controller.Start();
        }
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.