Cómo: Recibir notificaciones de excepciones de primera oportunidadHow to: Receive First-Chance Exception Notifications

El evento FirstChanceException de la clase AppDomain permite recibir una notificación de que se ha producido una excepción antes de que Common Language Runtime empiece a buscar controladores de excepciones.The FirstChanceException event of the AppDomain class lets you receive a notification that an exception has been thrown, before the common language runtime has begun searching for exception handlers.

El evento se genera en el nivel de dominio de aplicación.The event is raised at the application domain level. Un subproceso de ejecución puede pasar a través de varios dominios de aplicación, así que una excepción no controlada en un dominio de aplicación podría controlarse en otro.A thread of execution can pass through multiple application domains, so an exception that is unhandled in one application domain could be handled in another application domain. La notificación se produce en cada dominio de aplicación que haya agregado un controlador para el evento, hasta que un dominio de aplicación controle la excepción.The notification occurs in each application domain that has added a handler for the event, until an application domain handles the exception.

Los procedimientos y los ejemplos de este artículo muestran cómo recibir notificaciones de primera excepción en un programa sencillo con un dominio de aplicación y en un dominio de aplicación que cree.The procedures and examples in this article show how to receive first-chance exception notifications in a simple program that has one application domain, and in an application domain that you create.

Para ver un ejemplo más complejo que abarca varios dominios de aplicación, vaya al ejemplo del evento FirstChanceException.For a more complex example that spans several application domains, see the example for the FirstChanceException event.

Recepción de notificaciones de primera excepción en el dominio de aplicación predeterminadoReceiving First-Chance Exception Notifications in the Default Application Domain

En el siguiente procedimiento, el punto de entrada de la aplicación, el método Main(), se ejecuta en el dominio de aplicación predeterminado.In the following procedure, the entry point for the application, the Main() method, runs in the default application domain.

Para mostrar notificaciones de primera excepción en el dominio de aplicación predeterminadoTo demonstrate first-chance exception notifications in the default application domain

  1. Defina un controlador de eventos para el evento FirstChanceException mediante una función lambda y adjúntelo al evento.Define an event handler for the FirstChanceException event, using a lambda function, and attach it to the event. En este ejemplo, el controlador de eventos imprime el nombre del dominio de aplicación donde se ha controlado el evento y la propiedad Message de la excepción.In this example, the event handler prints the name of the application domain where the event was handled and the exception's Message property.

    using System;
    using System.Runtime.ExceptionServices;
    
    class Example
    {
        static void Main()
        {
            AppDomain.CurrentDomain.FirstChanceException += 
                (object source, FirstChanceExceptionEventArgs e) =>
                {
                    Console.WriteLine("FirstChanceException event raised in {0}: {1}",
                        AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
                };
    
    Imports System.Runtime.ExceptionServices
    
    Class Example
    
        Shared Sub Main()
        
            AddHandler AppDomain.CurrentDomain.FirstChanceException, 
                       Sub(source As Object, e As FirstChanceExceptionEventArgs)
                           Console.WriteLine("FirstChanceException event raised in {0}: {1}",
                                             AppDomain.CurrentDomain.FriendlyName, 
                                             e.Exception.Message)
                       End Sub
    
  2. Inicie una excepción y captúrela.Throw an exception and catch it. Antes de que el runtime busque el controlador de excepciones, se genera el evento FirstChanceException y se muestra un mensaje.Before the runtime locates the exception handler, the FirstChanceException event is raised and displays a message. Este mensaje va seguido del que muestra el controlador de excepciones.This message is followed by the message that is displayed by the exception handler.

    try
    {
        throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine("ArgumentException caught in {0}: {1}", 
            AppDomain.CurrentDomain.FriendlyName, ex.Message);
    }
    
    Try
        Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
    
    Catch ex As ArgumentException
        
        Console.WriteLine("ArgumentException caught in {0}: {1}", 
            AppDomain.CurrentDomain.FriendlyName, ex.Message)
    End Try
    
  3. Inicie una excepción, pero no la capture.Throw an exception, but do not catch it. Antes de que el runtime busque un controlador de excepciones, se genera el evento FirstChanceException y se muestra un mensaje.Before the runtime looks for an exception handler, the FirstChanceException event is raised and displays a message. No hay ningún controlador de excepciones, por lo que la aplicación finaliza.There is no exception handler, so the application terminates.

            throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
        }
    }
    
            Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
        End Sub
    End Class
    

    El código que se muestra en los tres primeros pasos de este procedimiento forma una aplicación de consola completa.The code that is shown in the first three steps of this procedure forms a complete console application. El resultado de la aplicación varía según el nombre del archivo .exe, porque el nombre del dominio de aplicación predeterminado consta del nombre y la extensión del archivo .exe.The output from the application varies, depending on the name of the .exe file, because the name of the default application domain consists of the name and extension of the .exe file. Vea el resultado del ejemplo siguiente.See the following for sample output.

    /* This example produces output similar to the following:
    
    FirstChanceException event raised in Example.exe: Thrown in Example.exe
    ArgumentException caught in Example.exe: Thrown in Example.exe
    FirstChanceException event raised in Example.exe: Thrown in Example.exe
    
    Unhandled Exception: System.ArgumentException: Thrown in Example.exe
       at Example.Main()
     */
    
    ' This example produces output similar to the following:
    '
    'FirstChanceException event raised in Example.exe: Thrown in Example.exe
    'ArgumentException caught in Example.exe: Thrown in Example.exe
    'FirstChanceException event raised in Example.exe: Thrown in Example.exe
    '
    'Unhandled Exception: System.ArgumentException: Thrown in Example.exe
    '   at Example.Main()
    

Recepción de notificaciones de primera excepción en otro dominio de aplicaciónReceiving First-Chance Exception Notifications in Another Application Domain

Si el programa contiene más de un dominio de aplicación, puede elegir cuáles reciben notificaciones.If your program contains more than one application domain, you can choose which application domains receive notifications.

Para recibir notificaciones de primera excepción en un dominio de aplicación que creeTo receive first-chance exception notifications in an application domain that you create

  1. Defina un controlador de eventos para el evento FirstChanceException.Define an event handler for the FirstChanceException event. En este ejemplo se usa un método static (Shared en Visual Basic) que imprime el nombre del dominio de aplicación donde se ha controlado el evento y la propiedad Message de la excepción.This example uses a static method (Shared method in Visual Basic) that prints the name of the application domain where the event was handled and the exception's Message property.

    static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
    }
    
    Shared Sub FirstChanceHandler(ByVal source As Object, 
                                  ByVal e As FirstChanceExceptionEventArgs)
    
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message)
    End Sub
    
  2. Cree un dominio de aplicación y agregue el controlador de eventos al evento FirstChanceException de ese dominio de aplicación.Create an application domain and add the event handler to the FirstChanceException event for that application domain. En este ejemplo, el dominio de aplicación se denomina AD1.In this example, the application domain is named AD1.

    AppDomain ad = AppDomain.CreateDomain("AD1");
    ad.FirstChanceException += FirstChanceHandler;
    
    Dim ad As AppDomain = AppDomain.CreateDomain("AD1")
    AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler
    

    Puede controlar este evento en el dominio de aplicación predeterminado de la misma manera.You can handle this event in the default application domain in the same way. Use la propiedad AppDomain.CurrentDomain static (Shared en Visual Basic) en Main() para obtener una referencia al dominio de aplicación predeterminado.Use the static (Shared in Visual Basic) AppDomain.CurrentDomain property in Main() to get a reference to the default application domain.

Para mostrar notificaciones de primera excepción en el dominio de aplicaciónTo demonstrate first-chance exception notifications in the application domain

  1. Cree un objeto Worker en el dominio de aplicación que ha creado en el procedimiento anterior.Create a Worker object in the application domain that you created in the previous procedure. La clase Worker debe ser pública y debe derivar de MarshalByRefObject, como se muestra en el ejemplo completo al final de este artículo.The Worker class must be public, and must derive from MarshalByRefObject, as shown in the complete example at the end of this article.

    Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                            typeof(Worker).Assembly.FullName, "Worker");
    
    Dim w As Worker = CType(ad.CreateInstanceAndUnwrap(
                                GetType(Worker).Assembly.FullName, "Worker"),
                            Worker)
    
  2. Llame a un método del objeto Worker que inicia una excepción.Call a method of the Worker object that throws an exception. En este ejemplo, se llama al método Thrower dos veces.In this example, the Thrower method is called twice. La primera vez, el argumento del método es true, lo que hace que el método capture su propia excepción.The first time, the method argument is true, which causes the method to catch its own exception. La segunda vez, el argumento es false y el método Main() captura la excepción en el dominio de aplicación predeterminado.The second time, the argument is false, and the Main() method catches the exception in the default application domain.

    // The worker throws an exception and catches it.
    w.Thrower(true);
    
    try
    {
        // The worker throws an exception and doesn't catch it.
        w.Thrower(false);
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine("ArgumentException caught in {0}: {1}", 
            AppDomain.CurrentDomain.FriendlyName, ex.Message);
    }
    
    ' The worker throws an exception and catches it.
    w.Thrower(true)
    
    Try
        ' The worker throws an exception and doesn't catch it.
        w.Thrower(false)
    
    Catch ex As ArgumentException
    
        Console.WriteLine("ArgumentException caught in {0}: {1}", 
            AppDomain.CurrentDomain.FriendlyName, ex.Message)
    End Try
    
  3. Coloque código en el método Thrower para controlar si el método controla su propia excepción.Place code in the Thrower method to control whether the method handles its own exception.

    if (catchException)
    {
        try
        {
            throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine("ArgumentException caught in {0}: {1}", 
                AppDomain.CurrentDomain.FriendlyName, ex.Message);
        }
    }
    else
    {
        throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
    }
    
    If catchException
    
        Try
            Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
    
        Catch ex As ArgumentException
        
            Console.WriteLine("ArgumentException caught in {0}: {1}", 
                AppDomain.CurrentDomain.FriendlyName, ex.Message)
        End Try
    Else
    
        Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
    End If
    

EjemploExample

En el ejemplo siguiente se crea un dominio de aplicación denominado AD1 y se agrega un controlador de eventos al evento FirstChanceException del dominio de aplicación.The following example creates an application domain named AD1 and adds an event handler to the application domain's FirstChanceException event. En el ejemplo se crea una instancia de la clase Worker en el dominio de aplicación y se llama a un método denominado Thrower que inicia una ArgumentException.The example creates an instance of the Worker class in the application domain, and calls a method named Thrower that throws an ArgumentException. Según el valor de su argumento, el método captura la excepción o no la controla.Depending on the value of its argument, the method either catches the exception or fails to handle it.

Cada vez que el método Thrower inicia una excepción en AD1, se genera el evento FirstChanceException en AD1 y el controlador de eventos muestra un mensaje.Each time the Thrower method throws an exception in AD1, the FirstChanceException event is raised in AD1, and the event handler displays a message. Luego el runtime busca un controlador de excepciones.The runtime then looks for an exception handler. En el primer caso, el controlador de excepciones se encuentra en AD1.In the first case, the exception handler is found in AD1. En el segundo caso, la excepción no se controla en AD1 y se captura en el dominio de aplicación predeterminado.In the second case, the exception is unhandled in AD1, and instead is caught in the default application domain.

Nota

El nombre del dominio de aplicación predeterminado es el mismo que el nombre del ejecutable.The name of the default application domain is the same as the name of the executable.

Si agrega un controlador para el evento FirstChanceException al dominio de aplicación predeterminado, el evento se genera y se controla antes de que el dominio de aplicación predeterminado controle la excepción.If you add a handler for the FirstChanceException event to the default application domain, the event is raised and handled before the default application domain handles the exception. Para verlo, agregue el código de C# AppDomain.CurrentDomain.FirstChanceException += FirstChanceException; (en Visual Basic, AddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException) al principio de Main().To see this, add the C# code AppDomain.CurrentDomain.FirstChanceException += FirstChanceException; (in Visual Basic, AddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException) at the beginning of Main().

using System;
using System.Reflection;
using System.Runtime.ExceptionServices;

class Example
{
    static void Main()
    {
        // To receive first chance notifications of exceptions in 
        // an application domain, handle the FirstChanceException
        // event in that application domain.
        AppDomain ad = AppDomain.CreateDomain("AD1");
        ad.FirstChanceException += FirstChanceHandler;

        // Create a worker object in the application domain.
        Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                                typeof(Worker).Assembly.FullName, "Worker");

        // The worker throws an exception and catches it.
        w.Thrower(true);

        try
        {
            // The worker throws an exception and doesn't catch it.
            w.Thrower(false);
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine("ArgumentException caught in {0}: {1}", 
                AppDomain.CurrentDomain.FriendlyName, ex.Message);
        }
    }

    static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
    }
}

public class Worker : MarshalByRefObject
{
    public void Thrower(bool catchException)
    {
        if (catchException)
        {
            try
            {
                throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine("ArgumentException caught in {0}: {1}", 
                    AppDomain.CurrentDomain.FriendlyName, ex.Message);
            }
        }
        else
        {
            throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
        }
    }
}

/* This example produces output similar to the following:

FirstChanceException event raised in AD1: Thrown in AD1
ArgumentException caught in AD1: Thrown in AD1
FirstChanceException event raised in AD1: Thrown in AD1
ArgumentException caught in Example.exe: Thrown in AD1
 */
Imports System.Reflection
Imports System.Runtime.ExceptionServices

Class Example
    Shared Sub Main()
    
        ' To receive first chance notifications of exceptions in 
        ' an application domain, handle the FirstChanceException
        ' event in that application domain.
        Dim ad As AppDomain = AppDomain.CreateDomain("AD1")
        AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler

        
        ' Create a worker object in the application domain.
        Dim w As Worker = CType(ad.CreateInstanceAndUnwrap(
                                    GetType(Worker).Assembly.FullName, "Worker"),
                                Worker)

        ' The worker throws an exception and catches it.
        w.Thrower(true)

        Try
            ' The worker throws an exception and doesn't catch it.
            w.Thrower(false)

        Catch ex As ArgumentException
        
            Console.WriteLine("ArgumentException caught in {0}: {1}", 
                AppDomain.CurrentDomain.FriendlyName, ex.Message)
        End Try
    End Sub

    Shared Sub FirstChanceHandler(ByVal source As Object, 
                                  ByVal e As FirstChanceExceptionEventArgs)
    
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message)
    End Sub
End Class

Public Class Worker
    Inherits MarshalByRefObject

    Public Sub Thrower(ByVal catchException As Boolean)
    
        If catchException
        
            Try
                Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)

            Catch ex As ArgumentException
            
                Console.WriteLine("ArgumentException caught in {0}: {1}", 
                    AppDomain.CurrentDomain.FriendlyName, ex.Message)
            End Try
        Else
        
            Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
        End If
    End Sub
End Class

' This example produces output similar to the following:
'
'FirstChanceException event raised in AD1: Thrown in AD1
'ArgumentException caught in AD1: Thrown in AD1
'FirstChanceException event raised in AD1: Thrown in AD1
'ArgumentException caught in Example.exe: Thrown in AD1

Vea tambiénSee also