AppDomain.UnhandledException イベント

定義

例外がキャッチされない場合に発生します。

public:
 event UnhandledExceptionEventHandler ^ UnhandledException;
public:
 virtual event UnhandledExceptionEventHandler ^ UnhandledException;
public event UnhandledExceptionEventHandler? UnhandledException;
public event UnhandledExceptionEventHandler UnhandledException;
[add: System.Security.SecurityCritical]
[remove: System.Security.SecurityCritical]
public event UnhandledExceptionEventHandler UnhandledException;
member this.UnhandledException : UnhandledExceptionEventHandler 
[<add: System.Security.SecurityCritical>]
[<remove: System.Security.SecurityCritical>]
member this.UnhandledException : UnhandledExceptionEventHandler 
Public Custom Event UnhandledException As UnhandledExceptionEventHandler 

イベントの種類

実装

属性

次の例では、 UnhandledException イベントを示します。 既定のアプリケーション ドメインでハンドルされない例外がスローされるたびに呼び出されるイベント ハンドラー ( MyHandler) を定義します。 その後、2 つの例外がスローされます。 1 つ目は try/catch ブロックによって処理されます。 2 つ目は未処理で、アプリケーションが終了する前に MyHandle ルーチンを呼び出します。

// The example should be compiled with the /clr:pure compiler option.
using namespace System;
using namespace System::Security::Permissions;

public ref class Example
{


private:
   static void MyHandler(Object^ sender, UnhandledExceptionEventArgs^ args)
   {
      Exception^ e = dynamic_cast<Exception^>(args->ExceptionObject);
      Console::WriteLine( "MyHandler caught : {0}", e->Message );
      Console::WriteLine("Runtime terminating: {0}", args->IsTerminating);
   }
   
public: 
   [SecurityPermissionAttribute( SecurityAction::Demand, ControlAppDomain = true )]
   static void Main()
   {
      AppDomain^ currentDomain = AppDomain::CurrentDomain;
      currentDomain->UnhandledException += gcnew UnhandledExceptionEventHandler(Example::MyHandler);
      try
      {
         throw gcnew Exception("1");
      }
      catch (Exception^ e) 
      {
         Console::WriteLine( "Catch clause caught : {0}\n", e->Message );
      }

      throw gcnew Exception("2");
   }
};

void main()
{
   Example::Main();
}   
// The example displays the following output:
//       Catch clause caught : 1
//       
//       MyHandler caught : 2
//       Runtime terminating: True
//       
//       Unhandled Exception: System.Exception: 2
//          at Example.Main()
//          at mainCRTStartup(String[] arguments)
using System;

public class Example
{
   public static void Main()
   {
      AppDomain currentDomain = AppDomain.CurrentDomain;
      currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);

      try {
         throw new Exception("1");
      } catch (Exception e) {
         Console.WriteLine("Catch clause caught : {0} \n", e.Message);
      }

      throw new Exception("2");
   }

   static void MyHandler(object sender, UnhandledExceptionEventArgs args)
   {
      Exception e = (Exception) args.ExceptionObject;
      Console.WriteLine("MyHandler caught : " + e.Message);
      Console.WriteLine("Runtime terminating: {0}", args.IsTerminating);
   }
}
// The example displays the following output:
//       Catch clause caught : 1
//
//       MyHandler caught : 2
//       Runtime terminating: True
//
//       Unhandled Exception: System.Exception: 2
//          at Example.Main()
open System
open System.Security.Permissions

let myHandler _ (args: UnhandledExceptionEventArgs) =
    let e = args.ExceptionObject :?> Exception
    printfn $"MyHandler caught : {e.Message}"
    printfn $"Runtime terminating: {args.IsTerminating}"

[<EntryPoint>]
let main _ =
    let currentDomain = AppDomain.CurrentDomain
    currentDomain.UnhandledException.AddHandler(UnhandledExceptionEventHandler myHandler)

    try
        failwith "1"
    with e ->
        printfn $"Catch clause caught : {e.Message} \n"

    failwith "2"

// The example displays the following output:
//       Catch clause caught : 1
//
//       MyHandler caught : 2
//       Runtime terminating: True
//
//       Unhandled Exception: System.Exception: 2
//          at Example.main()
Module Example
   Sub Main()
      Dim currentDomain As AppDomain = AppDomain.CurrentDomain
      AddHandler currentDomain.UnhandledException, AddressOf MyHandler
      
      Try
         Throw New Exception("1")
      Catch e As Exception
         Console.WriteLine("Catch clause caught : " + e.Message)
         Console.WriteLine()
      End Try
      
      Throw New Exception("2")
   End Sub
   
   Sub MyHandler(sender As Object, args As UnhandledExceptionEventArgs)
      Dim e As Exception = DirectCast(args.ExceptionObject, Exception)
      Console.WriteLine("MyHandler caught : " + e.Message)
      Console.WriteLine("Runtime terminating: {0}", args.IsTerminating)
   End Sub
End Module
' The example displays the following output:
'       Catch clause caught : 1
'       
'       MyHandler caught : 2
'       Runtime terminating: True
'       
'       Unhandled Exception: System.Exception: 2
'          at Example.Main()

注釈

例外が異なるスレッドからスローされた場合、ハンドラーが複数回呼び出されることがあります。

UnhandledException イベントは、キャッチされていない例外の通知を提供します。 これにより、システムの既定のハンドラーがユーザーに例外を報告し、アプリケーションを終了する前に、アプリケーションで例外に関する情報をログに記録できます。 アプリケーションの状態に関する十分な情報が得られる場合は、後で回復するためにプログラム データを保存するなど、他のアクションが実行される可能性があります。 例外が処理されないとプログラム データが破損する可能性があるため、注意が必要です。 ハンドラーは、例外がスローされた時点で保持されていたロックを維持しながら動作するため、デッドロックを引き起こす可能性がある他のリソースを待機しないよう注意する必要があります。

このイベントは、任意のアプリケーション ドメインで処理できます。 ただし、例外が発生したアプリケーション ドメインでイベントが発生するとは限りません。 例外は、該当する例外ハンドラーが見つからずにスレッドのスタック全体が巻き戻された場合にのみ処理されないため、イベントを発生できる最初の場所は、スレッドが発生したアプリケーション ドメイン内にあります。

UnhandledException イベントが既定のアプリケーション ドメインで処理される場合、スレッドが開始されたアプリケーション ドメインに関係なく、スレッド内のハンドルされない例外に対して発生します。 UnhandledExceptionのイベント ハンドラーを持つアプリケーション ドメインでスレッドが開始された場合、そのアプリケーション ドメインでイベントが発生します。 そのアプリケーション ドメインが既定のアプリケーション ドメインではなく、既定のアプリケーション ドメインにもイベント ハンドラーがある場合、イベントは両方のアプリケーション ドメインで発生します。

たとえば、スレッドがアプリケーション ドメイン "AD1" で起動し、アプリケーション ドメイン "AD2" でメソッドを呼び出し、そこからアプリケーション ドメイン "AD3" でメソッドを呼び出し、そこで例外をスローするとします。 UnhandledException イベントを発生できる最初のアプリケーション ドメインは "AD1" です。 そのアプリケーション ドメインが既定のアプリケーション ドメインでない場合は、既定のアプリケーション ドメインでもイベントを発生させることができます。

Note

共通言語ランタイムは、 UnhandledException イベントのイベント ハンドラーの実行中にスレッドの中止を中断します。

イベント ハンドラーに適切なフラグを持つ ReliabilityContractAttribute 属性がある場合、イベント ハンドラーは制約付き実行領域として扱われます。

このイベントは、イベント ハンドラーがセキュリティ クリティカルで、 HandleProcessCorruptedStateExceptionsAttribute 属性を持たない限り、スタック オーバーフローやアクセス違反などのプロセスの状態を破損する例外では発生しません。

このイベントのイベント ハンドラーを登録するには、必要なアクセス許可が必要です。または、 SecurityException がスローされます。

イベントの処理の詳細については、「処理とイベントの発生」を参照してください。

ハンドルされていない例外に関する他のイベント

特定のアプリケーション モデルの場合、メイン アプリケーション スレッドで未処理の例外が発生した場合、 UnhandledException イベントは他のイベントによって割り込まれる可能性があります。

Windows フォームを使用するアプリケーションでは、メイン アプリケーション スレッドでハンドルされない例外が発生すると、Application.ThreadException イベントが発生します。 このイベントが処理される場合、既定の動作では、ハンドルされない例外はアプリケーションを終了しませんが、アプリケーションは不明な状態のままです。 その場合、 UnhandledException イベントは発生しません。 この動作は、アプリケーション構成ファイルを使用するか、Application.SetUnhandledExceptionMode メソッドを使用して、UnhandledExceptionMode.ThrowException イベント ハンドラーがフックされる前にモードをThreadExceptionに変更することで変更できます。 これは、メイン アプリケーション スレッドにのみ適用されます。 UnhandledException イベントは、他のスレッドでスローされた未処理の例外に対して発生します。

Visual Basic アプリケーション フレームワークは、メイン アプリケーション スレッド ( WindowsFormsApplicationBase.UnhandledException イベント) でハンドルされない例外に対して別のイベントを提供します。 このイベントには、 AppDomain.UnhandledExceptionで使用されるイベント引数オブジェクトと同じ名前のイベント引数オブジェクトがありますが、プロパティは異なります。 特に、このイベント引数オブジェクトには、アプリケーションの実行を継続し、ハンドルされない例外を無視して (アプリケーションを不明な状態のままにする) ExitApplication プロパティがあります。 その場合、 AppDomain.UnhandledException イベントは発生しません。

適用対象