42
protected override void OnStart(string[] args) 
{ 
    AppDomain.CurrentDomain.UnhandledException += 
     new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 

    Thread.Sleep(10000); 

    throw new Exception(); 
} 

void CurrentDomain_UnhandledException(object sender, 
             UnhandledExceptionEventArgs e) 
{ 
} 

내 Windows 서비스에서 위 코드에 디버거를 연결하고 CurrentDomain_UnhandledException에 중단 점을 설정했지만 충돌이 발생하지 않았습니다. 예외 처리가 처리되지 않는다는 메시지가 뜨면 서비스가 중단됩니다. 이벤트 핸들러에 코드를 두어 보았습니다.Windows 서비스에서 .NET UnhandledException 처리를 설정하려면 어떻게해야합니까?

Windows 서비스에서 처리되지 않은 예외 처리를 설정하는 적절한 방법이 아닌가요?

답변

2

그냥 궁금해서, 당신은 무엇을 달성하려고 : 서비스 충돌을 피하거나 오류를보고?

보고를 위해 최선의 방법은 최상위 try/catch 문을 추가하는 것입니다. 로그 파일을 Windows 이벤트 로그 및/또는 로그 파일에 기록 할 수 있습니다. 성공적으로 서비스를 중지 할 때까지

은 또한 0이 아닌 값으로 ExitCode 속성을 설정할 수 있습니다. 시스템 관리자가 서비스 제어판에서 서비스를 시작하고 서비스가 갑자기 0이 아닌 종료 코드로 중단되면 Windows는 오류에 대한 설명과 함께 오류 메시지를 표시 할 수 있습니다.

+0

디버깅. 나는 모든 예외를 잡으려고 노력했다. 그러나 사람은 어떻게 든 나를 도주하고있다. 나는 이것이 더 다루기 쉬운 해결책이라고 생각했다. –

+0

OnStart 또는 OnStop에서 예외가 발생합니까? 예외에 대한 다른 정보가 있습니까? –

9

Windows 서비스에서는 OnStart 메서드에서 많은 코드를 실행하고 싶지 않습니다. 서비스 스레드를 시작한 다음 리턴하는 코드 만 있으면됩니다.

이렇게하면 서비스 스레드에서 발생하는 예외를 처리 할 수 ​​있습니다.

public static void Start() 
{ 
    AppDomain currentDomain = AppDomain.CurrentDomain; 
    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException); 

    running = true; 
    ThreadStart ts = new ThreadStart(ServiceThreadBody); 
    thread = new Thread(ts); 
    thread.Name = "ServiceThread"; 
    thread.Priority = ThreadPriority.BelowNormal; 
    thread.Start(); 
} 
+0

나는 최근에 내 서비스가 여전히 실행되지만 아무런 처리도하지 않는 곳을 가지고있다 ... "삼켜 버린"예외로 인한 것일 수 있다고 생각하기 시작했다. 내 문제에 대해 의견이 있으시면 궁금한 점이 있으십니까? http://stackoverflow.com/questions/41618324/windows-service-runs-but-stops-processing-after-two-days –

4

이 스레드는 약간 오래된 것이지만 .NET에서 Windows 서비스를 개발하는 개인적인 경험에 기반하여 몇 가지 의견을 추가하는 것이 유용 할 것이라고 생각했습니다. 가장 좋은 방법은 서비스 제어 관리자에서만큼 개발을 피하는 것입니다.이 경우 서비스 시작 방법을 모방 한 간단한 하네이 필요합니다. 서비스 클래스의 인스턴스를 만들 수 있습니다. ServiceBase에서 이미 파생 됨) OnStart, OnStop 등의 메소드를 호출하십시오. 이 하네스는 원하는대로 콘솔 앱 또는 Windows 앱이 될 수 있습니다.

이 꽤 많이 나는 .NET에서 디버깅 서비스 시작 문제의 발견 유일한 방법입니다 - 코드, Visual Studio 및 실제 서비스 제어 관리자 사이의 상호 작용은 단지 그렇지 않으면 처리가 불가능합니다.

HTH.

+0

+1 : 별도의 라이브러리에 모든 논리를 구현하고 서비스에서 호출하십시오. 개발/디버깅을 위해 콘솔 응용 프로그램에서 동일한 라이브러리를 호출하십시오. –

+2

나는 귀하의 접근 방식을 좋아하지만 서비스 시작 문제를 디버그하는 유일한 방법은 아닙니다. 특히 프로덕션 환경에서 서비스를 디버깅 할 때 WinDbg을 다음과 같이 설정하는 것입니다. 1. 호스트 프로세스가 시작될 때 서비스에 연결하고 2. 서비스 격리를 극복하기 위해 필요한 수신 포트를 엽니 다. 그런 다음 사용자 세션에서 실행중인 WinDbg의 다른 인스턴스를 사용하여 디버깅을 시작할 수 있습니다. (첫 번째 문으로 "RequestAdditionalTime"에 대한 구성 가능한 호출 또는 레지스트리 구성은 SCM이 서비스 시작 시간에 적용 할 수있는 시간 제한을 극복하는 데 도움이 됨) –

51

는 차라리 말이 글에 왔어요,하지만 난 다른 답변 중 어느 것도 포기하지 설명을 제공하는 가치가있을 수도 생각했다.

CurrentDomain_UnhandledException 처리기가 OP 코드 샘플에서 히트되지 않는 이유는 Windows 서비스 제어 관리자의 시작 명령에 대한 응답으로 OnStart 메서드가 호출 되었기 때문입니다.이 명령은 프레임 워크의 명령에 의해이 메서드에 전달되고이 메서드에 전달됩니다 ServiceBase 구현); OnStart에 의해 throw 된 모든 예외는 기본 클래스에서 처리되고 이벤트 로그에 기록되며 SCM에 반환 된 오류 상태 코드로 변환됩니다. 따라서 예외는 AppDomain의 처리되지 않은 예외 처리기로 전파되지 않습니다.

의 작업자 스레드에서 처리되지 않은 예외가 발생하면CurrentDomain_UnhandledException 처리기로 포착됩니다.

+0

ServiceBase에서이 동작을 일으키는 ServiceQueuedMainCallback 메서드 인 것처럼 보입니다. –

2

내 자신의 Windows 서비스로 작업하고있을 때, 이상하게도 충분히 멈추고있었습니다. 나는 그것이 예외로 인한 것이라고 생각했다. 지금 나는 텍스트 파일에 손쉽게 예외를 잡는다. 우선 텍스트 파일에 기록을 남기기 때문에 C 위치에 새 파일 ServiceLog.txt를 만들어야합니다. 아래 코드를 사용하면 줄 번호가있는 모든 예외를 처리 할 수 ​​있습니다.

using System.Security.Permissions; 
using System.IO; 

[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)] 
    protected override void OnStart(string[] args) 
    { AppDomain currentDomain = AppDomain.CurrentDomain; 
     currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); 
     ... 
     Your codes... 
     .... 
    } 
    void MyHandler(object sender, UnhandledExceptionEventArgs args) 
    { 
     Exception e = (Exception)args.ExceptionObject; 
     WriteToFile("Simple Service Error on: {0} " + e.Message + e.StackTrace); 
    } 
    private void WriteToFile(string text) 
    { 
     string path = "C:\\ServiceLog.txt"; 
     using (StreamWriter writer = new StreamWriter(path, true)) 
     { 
      writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))); 
      writer.Close(); 
     } 
    } 
관련 문제