26

Windows サービスで UnhandledException ハンドラを使用することは可能ですか?

通常、私は、ログ記録、家への電話などを行うカスタム ビルドの例外処理コンポーネントを使用します。このコンポーネントは、System.AppDomain.CurrentDomain.UnhandledException にハンドラーを追加しますが、私が知る限り、これは何も達成せず、Windows サービスに勝てません。最終的に、2 つ (または 4 つ) の Service エントリ ポイントで次のパターンになります。


    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.
        Try
            MyServiceComponent.Start()
        Catch ex As Exception
            'call into our exception handler
            MyExceptionHandlingComponent.ManuallyHandleException (ex)
            'zero is the default ExitCode for a successfull exit, so if we set it to non-zero
            ExitCode = -1
            'So, we use Environment.Exit, it seems to be the most appropriate thing to use
            'we pass an exit code here as well, just in case.
            System.Environment.Exit(-1)
        End Try
    End Sub

OnStart を面倒な例外処理配管で埋める必要がないように、カスタム例外処理コンポーネントがこれをより適切に処理できる方法はありますか?

4

2 に答える 2

16

わかりました、私は今これについてもう少し研究をしました。.Net で Windows サービスを作成する場合、System.ServiceProcess.ServiceBase から継承するクラスを作成します (VB では、これは .Designer.vb ファイルに隠されています)。次に、OnStart 関数と OnStop 関数をオーバーライドし、必要に応じて OnPause と OnContinue をオーバーライドします。これらのメソッドは基本クラス内から呼び出されるため、リフレクターを少しいじりました。OnStart は、ServiceQueuedMainCallback と呼ばれる System.ServiceProcess.ServiceBase のメソッドによって呼び出されます。私のマシンの「System.ServiceProcess、Version = 2.0.0.0」のバージョンは、次のように逆コンパイルされます。


Private Sub ServiceQueuedMainCallback(ByVal state As Object)
    Dim args As String() = DirectCast(state, String())
    Try 
        Me.OnStart(args)
        Me.WriteEventLogEntry(Res.GetString("StartSuccessful"))
        Me.status.checkPoint = 0
        Me.status.waitHint = 0
        Me.status.currentState = 4
    Catch exception As Exception
        Me.WriteEventLogEntry(Res.GetString("StartFailed", New Object() { exception.ToString }), EventLogEntryType.Error)
        Me.status.currentState = 1
    Catch obj1 As Object
        Me.WriteEventLogEntry(Res.GetString("StartFailed", New Object() { String.Empty }), EventLogEntryType.Error)
        Me.status.currentState = 1
    End Try
    Me.startCompletedSignal.Set
End Sub

したがって、Me.OnStart(args) は Try Catch ブロックの Try 部分内から呼び出されるため、OnStart メソッド内で発生することはすべて、その Try Catch ブロックによって効果的にラップされるため、発生した例外は技術的に未処理であると想定します。それらは実際には ServiceQueuedMainCallback Try Catch で処理されます。したがって、CurrentDomain.UnhandledException は、少なくともスタートアップ ルーチン中に実際に発生することはありません。他の 3 つのエントリ ポイント (OnStop、OnPause、および OnContinue) はすべて、同様の方法で基本クラスから呼び出されます。

したがって、例外処理コンポーネントが Start と Stop で UnhandledException をキャッチできない理由を説明していると思いますが、OnStart で設定されたタイマーが起動時に UnhandledException を発生させない理由を説明しているかどうかはわかりません。

于 2008-09-12T07:30:04.107 に答える
2

AppDomain.UnhandledException イベントをサブスクライブできます。メッセージ ループがある場合は、Application.ThreadException イベントに関連付けることができます。

于 2008-09-12T06:25:51.767 に答える