Información general sobre la administración de aplicaciones

Todas las aplicaciones suelen compartir un conjunto común de funciones que se aplica a la implementación y la administración de la aplicación. En este tema se proporciona información general sobre la función de la clase Application para crear y administrar aplicaciones.

La clase Application

En WPF, la función común en el ámbito de aplicación se encapsula en la clase Application. La clase Application incluye las funciones siguientes:

  • Realizar el seguimiento e interactuar con la duración de la aplicación.

  • Recuperar y procesar los parámetros de la línea de comandos.

  • Detectar y responder a las excepciones no controladas.

  • Compartir propiedades y recursos en el ámbito de aplicación.

  • Administrar ventanas en las aplicaciones independientes.

  • Seguimiento y administración de la navegación.

Cómo realizar las tareas comunes con la clase Application

Si no está interesado en todos los detalles de la clase Application, en la tabla siguiente se muestran algunas de las tareas comunes para Application y cómo realizarlas. Viendo las API y los temas relacionados, puede buscar más información y código de ejemplo.

Tarea Enfoque
Obtener un objeto que representa la aplicación actual Utilice la propiedad Application.Current.
Agregar una pantalla de inicio a una aplicación Vea Agregar una pantalla de presentación a una aplicación WPF.
Iniciar una aplicación Use el método Application.Run.
Detener una aplicación Use el método Shutdown del objeto Application.Current.
Obtener los argumentos de la línea de comandos Controle el evento Application.Startup y use la propiedad StartupEventArgs.Args. Para ver un ejemplo, consulte el evento Application.Startup.
Obtener y establecer el código de salida de la aplicación Establezca la propiedad ExitEventArgs.ApplicationExitCode en el controlador de eventos Application.Exit o llame al método Shutdown y páselo en un entero.
Detectar y responder a las excepciones no controladas Controle el evento DispatcherUnhandledException.
Obtener y establecer recursos en el ámbito de aplicación Utilice la propiedad Application.Resources.
Usar un diccionario de recursos en el ámbito de aplicación Vea Usar un diccionario de recursos en el ámbito de aplicación.
Obtener y establecer propiedades en el ámbito de aplicación Utilice la propiedad Application.Properties.
Obtener y guardar el estado de una aplicación Vea Conservar y restaurar propiedades en el ámbito de aplicación a través de sesiones de aplicación.
Administrar archivos de datos que no son de código, incluidos los archivos de recursos, los archivos de contenido y los archivos de sitio de origen. Vea Archivos de recursos, contenido y datos de aplicaciones de WPF.
Administrar ventanas en las aplicaciones independientes Vea WPF Windows Overview (Introducción a Windows Presentation Foundation).
Realizar un seguimiento y administrar la navegación Vea Información general sobre navegación.

La definición de aplicación

Para usar la función de la clase Application, debe implementar una definición de aplicación. Una definición de aplicación WPF es una clase que deriva de Application y se configura con un valor de MSBuild especial.

Implementar una definición de aplicación

Una definición de aplicación WPF típica se implementa usando tanto marcado como código subyacente. Esto le permite usar marcado para establecer mediante declaración propiedades, recursos y eventos de registro de la aplicación, mientras que el control de eventos y la implementación del comportamiento específico de la aplicación se realizan en el código subyacente.

En el ejemplo siguiente se muestra cómo implementar una definición de aplicación usando tanto marcado como código subyacente:

<Application 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  x:Class="SDKSample.App" />
using System.Windows;

namespace SDKSample
{
    public partial class App : Application { }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class App
        Inherits Application
    End Class
End Namespace

Para que un archivo de marcado y un archivo de código subyacente funcionen conjuntamente, debe ocurrir lo siguiente:

  • En el marcado, el elemento Application debe incluir el atributo x:Class. Cuando se compila la aplicación, la existencia de x:Class en el archivo de marcación provoca que MSBuild cree una clase partial que deriva de Application y tiene el nombre especificado por el atributo x:Class. Para esto es necesario agregar una declaración de espacio de nombres XML para el esquema XAML (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml").

  • En el código subyacente, la clase debe ser una instancia de partial con el mismo nombre especificado mediante el atributo x:Class en el marcado y debe derivarse de Application. Esto permite que el archivo de código subyacente se asocie a la clase partial que se genera para el archivo de marcación cuando se compila la aplicación (consulte Compilar una aplicación de WPF).

Nota

Al crearse un nuevo proyecto de Aplicación WPF o Aplicación de explorador WPF mediante Visual Studio, se incluye de manera predeterminada una definición de aplicación, que se define usando tanto marcado como código subyacente.

Este código es el mínimo necesario para implementar una definición de aplicación. En cambio, es necesario realizar una configuración adicional de MSBuild en la definición de aplicación antes de compilar y ejecutar la aplicación.

Configurar la definición de aplicación para MSBuild

Las aplicaciones independientes y aplicaciones del explorador XAML (XBAP) requieren la implementación de un cierto nivel de infraestructura para poderse ejecutar. La parte más importante de esta infraestructura es el punto de entrada. Cuando un usuario inicia una aplicación, el sistema operativo llama al punto de entrada, que es una función conocida para iniciar las aplicaciones.

Advertencia

Las aplicaciones XBAP requieren exploradores heredados, como Internet Explorer y Firefox. Estas versiones anteriores del explorador suelen no ser compatibles con Windows 10 y Windows 11. Los exploradores modernos ya no admiten la tecnología necesaria para las aplicaciones XBAP debido a riesgos de seguridad. Los complementos que habilitan XBAPs ya no se admiten.

Tradicionalmente, los desarrolladores necesitaban escribir todo o parte de este código, según la tecnología. En cambio, WPF se encarga de generar este código cuando el archivo de marcado de la definición de aplicación está configurado como un elemento ApplicationDefinition de MSBuild, tal como se muestra en el siguiente archivo de proyecto de MSBuild:

<Project
  DefaultTargets="Build"
                        xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <ApplicationDefinition Include="App.xaml" />
  <Compile Include="App.xaml.cs" />
  ...
</Project>

Dado que el archivo de código subyacente contiene código, se marca como un elemento Compile de MSBuild, lo cual es normal.

La aplicación de estas configuraciones de MSBuild a los archivos de código subyacente y marcado de una definición de aplicación hace que MSBuild genere código como el siguiente:

using System;
using System.Windows;

namespace SDKSample
{
    public class App : Application
    {
        public App() { }
        [STAThread]
        public static void Main()
        {
            // Create new instance of application subclass
            App app = new App();

            // Code to register events and set properties that were
            // defined in XAML in the application definition
            app.InitializeComponent();

            // Start running the application
            app.Run();
        }

        public void InitializeComponent()
        {
            // Initialization code goes here.
        }
    }
}
Imports System.Windows

Namespace SDKSample
    Public Class App
        Inherits Application
        Public Sub New()
        End Sub
        <STAThread>
        Public Shared Sub Main()
            ' Create new instance of application subclass
            Dim app As New App()

            ' Code to register events and set properties that were
            ' defined in XAML in the application definition
            app.InitializeComponent()

            ' Start running the application
            app.Run()
        End Sub

        Public Sub InitializeComponent()
            ' Initialization code goes here.	
        End Sub
    End Class
End Namespace

El código resultante amplía la definición de aplicación con código de infraestructura adicional, que incluye el método de punto de entrada Main. El atributo STAThreadAttribute se aplica al método Main para indicar que el subproceso principal de la interfaz de usuario para la aplicación de WPF es un subproceso STA, necesario para las aplicaciones WPF. Cuando se invoca, Main crea una nueva instancia de App antes de llamar al método InitializeComponent para registrar los eventos y establecer las propiedades que se implementan en el marcado. Dado que se genera InitializeComponent, no es necesario llamar explícitamente a InitializeComponent desde una definición de aplicación tal y como se hace para las implementaciones Page y Window. Finalmente, se llama al método Run para iniciar la aplicación.

Obtener la aplicación actual

Dado que la función de la clase Application se comparte en una aplicación, solo puede haber una instancia de la clase Application por AppDomain. Para exigir esto, la clase Application se implementa como una clase singleton (vea Implementing Singleton in C# [Implementar Singleton en C#]), que crea una única instancia de sí misma y proporciona acceso compartido a ella con la propiedad staticCurrent.

En el código siguiente se muestra cómo adquirir una referencia al objeto Application para el objeto AppDomain actual.

// Get current application
Application current = App.Current;
' Get current application
Dim current As Application = App.Current

Current devuelve una referencia a una instancia de la clase Application. Si quiere obtener una referencia a la clase derivada Application, debe convertir el valor de la propiedad Current, como se muestra en el ejemplo siguiente.

// Get strongly-typed current application
App app = (App)App.Current;
' Get strongly-typed current application
Dim appCurrent As App = CType(App.Current, App)

Puede inspeccionar el valor de Current en cualquier punto de la duración de un objeto Application. En cambio, se recomienda tener cuidado. Tras crearse una instancia de la clase Application, el estado del objeto Application es incoherente durante un período de tiempo. Durante este período, Application realiza las diversas tareas de inicialización necesarias para que se ejecute el código, incluido el establecimiento de la infraestructura de la aplicación, la configuración de las propiedades y el registro de los eventos. Si intenta usar el objeto Application durante este período, el código puede generar resultados inesperados, en particular si depende de las diversas propiedades de Application que se están estableciendo.

Cuando Application completa sus tareas de inicialización, se inicia realmente su duración.

Duración de la aplicación

La duración de una aplicación WPF está marcada por varios eventos que Application provoca para indicar cuándo se inicia la aplicación, cuándo se activa y se desactiva, y cuándo se cierra.

Pantalla de presentación

A partir de .NET Framework 3.5 SP1, puede especificar una imagen para usarla en una ventana de inicio o pantalla de presentación. La clase SplashScreen facilita el mostrar una ventana de inicio mientras se carga la aplicación. La ventana SplashScreen se crea y muestra antes de que se llame a Run. Para obtener más información, vea Tiempo de inicio de una aplicación y Cómo: Agregar una pantalla de presentación a una aplicación WPF.

Iniciar una aplicación

Después de llamar a Run e inicializar la aplicación, esta está lista para ejecutarse. El evento Startup indica este momento cuando se genera:

using System.Windows;

namespace SDKSample
{
    public partial class App : Application
    {
        void App_Startup(object sender, StartupEventArgs e)
        {
            // Application is running
        }
    }
}

Namespace SDKSample
    Partial Public Class App
        Inherits Application
        Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
            ' Application is running
            '</SnippetStartupCODEBEHIND1>
    End Class
End Namespace
'</SnippetStartupCODEBEHIND2>

En este punto de la duración de una aplicación, se suele mostrar una interfaz de usuario.

Mostrar una interfaz de usuario

La mayoría de las aplicaciones independientes para Windows abren un objeto Window cuando comienzan a ejecutarse. El controlador de eventos Startup es una de las ubicaciones donde se puede hacer esto, tal como se muestra en el código siguiente.

<Application
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.App" 
  Startup="App_Startup" />
using System.Windows;

namespace SDKSample
{
    public partial class App : Application
    {
        void App_Startup(object sender, StartupEventArgs e)
        {
            // Open a window
            MainWindow window = new MainWindow();
            window.Show();
        }
    }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class App
        Inherits Application
        Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
            ' Open a window
            Dim window As New MainWindow()
            window.Show()
        End Sub
    End Class
End Namespace

Nota

El primer objeto Window del que se va a crear una instancia en una aplicación independiente se convierte de manera predeterminada en la ventana principal de la aplicación. A este objeto Window se hace referencia mediante la propiedad Application.MainWindow. El valor de la propiedad MainWindow se puede cambiar mediante programación si una ventana diferente del primer objeto Window del que se creó una instancia debe ser la ventana principal.

Cuando se inicia por primera vez una aplicación XBAP, lo más probable es que navegue a un objeto Page. Esto se muestra en el código siguiente.

<Application 
  x:Class="SDKSample.App"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Startup="App_Startup" />
using System;
using System.Windows;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class App : Application
    {
        void App_Startup(object sender, StartupEventArgs e)
        {
            ((NavigationWindow)this.MainWindow).Navigate(new Uri("HomePage.xaml", UriKind.Relative));
        }
    }
}

Imports System.Windows
Imports System.Windows.Navigation

Namespace SDKSample
    Partial Public Class App
        Inherits Application
        Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
            CType(Me.MainWindow, NavigationWindow).Navigate(New Uri("HomePage.xaml", UriKind.Relative))
        End Sub
    End Class
End Namespace

Si controla Startup para que abra solamente un objeto Window o navegue a un objeto Page, podrá establecer el atributo StartupUri en el marcado.

En el ejemplo siguiente se muestra cómo usar StartupUri desde una aplicación independiente para abrir un objeto Window.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="MainWindow.xaml" />

En el ejemplo siguiente se muestra cómo usar la propiedad StartupUri de una aplicación XBAP para navegar a un objeto Page.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="HomePage.xaml" />

Este marcado tiene el mismo efecto que el código anterior para abrir una ventana.

Nota

Para obtener más información sobre la navegación, vea Información general sobre navegación.

Debe controlar el evento Startup para que se abra un objeto Window si necesita crear instancias del mismo mediante un constructor no predeterminado, o si necesita establecer sus propiedades o suscribirse a sus eventos antes de que se muestre, o bien, si necesita procesar los argumentos de línea de comandos proporcionados al iniciarse la aplicación.

Procesar argumentos de la línea de comandos

En Windows, las aplicaciones independientes pueden iniciarse desde el símbolo del sistema o desde el escritorio. En ambos casos, es posible pasar argumentos de la línea de comandos a la aplicación. En el ejemplo siguiente se muestra una aplicación que se inicia con un solo argumento de la línea de comandos, "/StartMinimized":

wpfapplication.exe /StartMinimized

Durante la inicialización de la aplicación, WPF recupera los argumentos de la línea de comandos del sistema operativo y los pasa al controlador de eventos Startup a través de la propiedad Args del parámetro StartupEventArgs. Puede recuperar y almacenar los argumentos de la línea de comandos usando código como el siguiente.

<Application
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.App"
  Startup="App_Startup" />
using System.Windows;

namespace SDKSample
{
    public partial class App : Application
    {
        void App_Startup(object sender, StartupEventArgs e)
        {
            // Application is running
            // Process command line args
            bool startMinimized = false;
            for (int i = 0; i != e.Args.Length; ++i)
            {
                if (e.Args[i] == "/StartMinimized")
                {
                    startMinimized = true;
                }
            }

            // Create main application window, starting minimized if specified
            MainWindow mainWindow = new MainWindow();
            if (startMinimized)
            {
                mainWindow.WindowState = WindowState.Minimized;
            }
            mainWindow.Show();
        }
    }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class App
        Inherits Application
        Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
            ' Application is running
            ' Process command line args
            Dim startMinimized As Boolean = False
            Dim i As Integer = 0
            Do While i <> e.Args.Length
                If e.Args(i) = "/StartMinimized" Then
                    startMinimized = True
                End If
                i += 1
            Loop

            ' Create main application window, starting minimized if specified
            Dim mainWindow As New MainWindow()
            If startMinimized Then
                mainWindow.WindowState = WindowState.Minimized
            End If
            mainWindow.Show()
        End Sub
    End Class
End Namespace

El código controla el evento Startup para comprobar si se ha proporcionado el argumento de la línea de comandos /StartMinimized; en caso afirmativo, abre la ventana principal con un WindowState de Minimized. Observe que, dado que la propiedad WindowState debe establecerse mediante programación, el objeto Window principal se debe abrir explícitamente en el código.

Las aplicaciones XBAP no pueden recuperar ni procesar los argumentos de la línea de comandos porque se inician usando la implementación de ClickOnce (vea Implementar una aplicación de WPF). En cambio, pueden recuperar y procesar los parámetros de las cadenas de consulta de las direcciones URL que se usan para iniciarlas.

Activación y desactivación de aplicaciones

Windows permite a los usuarios cambiar de una aplicación a otra. El método más común es usar la combinación de teclas ALT+TAB. Solamente se puede cambiar a una aplicación si tiene un objeto Window visible que el usuario pueda seleccionar. El objeto Window seleccionado actualmente es la ventana activa (también conocida como ventana de primer plano) y es el objeto Window que recibe los datos proporcionados por el usuario. La aplicación con la ventana activa es la aplicación activa (o aplicación de primer plano). Una aplicación se convierte en la aplicación activa en las siguientes circunstancias:

  • Se inicia y muestra un objeto Window.

  • Un usuario cambia desde otra aplicación seleccionando un objeto Window de la aplicación.

Para detectar cuándo una aplicación se convierte en la aplicación activa, controle el evento Application.Activated.

De manera similar, una aplicación puede volverse inactiva en las circunstancias siguientes:

  • Un usuario cambia a otra aplicación desde la actual.

  • Cuando se cierra la aplicación.

Para detectar cuándo una aplicación se vuelve inactiva, controle el evento Application.Deactivated.

En el código siguiente se muestra cómo controlar los eventos Activated y Deactivated para determinar si una aplicación está activa.

<Application 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.App"
  StartupUri="MainWindow.xaml"
  Activated="App_Activated" 
  Deactivated="App_Deactivated" />
using System;
using System.Windows;

namespace SDKSample
{
    public partial class App : Application
    {
        bool isApplicationActive;

        void App_Activated(object sender, EventArgs e)
        {
            // Application activated
            this.isApplicationActive = true;
        }

        void App_Deactivated(object sender, EventArgs e)
        {
            // Application deactivated
            this.isApplicationActive = false;
        }
    }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class App
        Inherits Application
        Private isApplicationActive As Boolean

        Private Sub App_Activated(ByVal sender As Object, ByVal e As EventArgs)
            ' Application activated
            Me.isApplicationActive = True
        End Sub

        Private Sub App_Deactivated(ByVal sender As Object, ByVal e As EventArgs)
            ' Application deactivated
            Me.isApplicationActive = False
        End Sub
    End Class
End Namespace

Un objeto Window también se puede activar y desactivar. Para obtener más información, vea Window.Activated y Window.Deactivated.

Nota

En el caso de las aplicaciones XBAP, no se provoca el evento Application.Activated ni Application.Deactivated.

Cierre de la aplicación

La duración de una aplicación finaliza cuando se cierra, lo cual puede ocurrir por las razones siguientes:

  • El usuario cierra todos los objetos Window.

  • El usuario cierra el objeto Window principal.

  • El usuario finaliza la sesión de Windows cerrando sesión o apagando.

  • Se ha cumplido una condición específica de la aplicación.

Para facilitar la administración del cierre de la aplicación, Application proporciona el método Shutdown, la propiedad ShutdownMode y los eventos SessionEnding y Exit.

Nota

Solamente se puede llamar a Shutdown desde aplicaciones que tengan UIPermission. Las aplicaciones WPF independientes siempre tienen este permiso. En cambio, las aplicaciones XBAP que se ejecutan en el recinto de seguridad de confianza parcial de la zona de Internet no lo tienen.

Modo de apagado

La mayoría de las aplicaciones se apagan cuando se cierran todas las ventanas o cuando se cierra la ventana principal. En ocasiones, en cambio, puede haber otras condiciones específicas de la aplicación que determinen cuándo se cierra la aplicación. Puede especificar las condiciones en las que se cerrará la aplicación estableciendo la propiedad ShutdownMode en uno de los valores siguientes de la enumeración ShutdownMode:

El valor predeterminado de ShutdownMode es OnLastWindowClose, lo que significa que una aplicación se cierra automáticamente cuando el usuario cierra la última ventana de la aplicación. En cambio, si la aplicación debe cerrarse cuando se cierre la ventana principal, WPF lo hará automáticamente si establece ShutdownMode en OnMainWindowClose. Esto se muestra en el ejemplo siguiente.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App"
    ShutdownMode="OnMainWindowClose" />

En el caso de condiciones de cierre específicas de la aplicación, establezca ShutdownMode en OnExplicitShutdown. En este caso, es su responsabilidad cerrar la aplicación llamando explícitamente al método Shutdown; de lo contrario, la aplicación seguirá ejecutándose aunque se cierren todas las ventanas. Observe que se llama implícitamente a Shutdown cuando el valor de ShutdownMode es OnLastWindowClose o OnMainWindowClose.

Nota

ShutdownMode se puede establecer desde una aplicación XBAP, pero se omite; una aplicación XBAP siempre se cierra cuando se navega fuera de ella en un explorador o cuando se cierra el explorador que hospeda la aplicación XBAP. Para obtener más información, consulte Información general sobre navegación.

Fin de la sesión

Las condiciones de apagado que describe la propiedad ShutdownMode son específicas de la aplicación. En algunos casos, en cambio, es posible que una aplicación se cierre como resultado de una condición externa. La condición externa más común se produce cuando el usuario finaliza la sesión de Windows mediante las acciones siguientes:

  • Cerrar sesión

  • Apagar

  • Reiniciar

  • Hibernar

Para detectar cuándo finaliza una sesión de Windows, puede controlar el evento SessionEnding, tal como se muestra en el ejemplo siguiente.

<Application 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App"
    StartupUri="MainWindow.xaml"
    SessionEnding="App_SessionEnding" />
using System.Windows;

namespace SDKSample
{
    public partial class App : Application
    {
        void App_SessionEnding(object sender, SessionEndingCancelEventArgs e)
        {
            // Ask the user if they want to allow the session to end
            string msg = string.Format("{0}. End session?", e.ReasonSessionEnding);
            MessageBoxResult result = MessageBox.Show(msg, "Session Ending", MessageBoxButton.YesNo);

            // End session, if specified
            if (result == MessageBoxResult.No)
            {
                e.Cancel = true;
            }
        }
    }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class App
        Inherits Application
        Private Sub App_SessionEnding(ByVal sender As Object, ByVal e As SessionEndingCancelEventArgs)
            ' Ask the user if they want to allow the session to end
            Dim msg As String = String.Format("{0}. End session?", e.ReasonSessionEnding)
            Dim result As MessageBoxResult = MessageBox.Show(msg, "Session Ending", MessageBoxButton.YesNo)

            ' End session, if specified
            If result = MessageBoxResult.No Then
                e.Cancel = True
            End If
        End Sub
    End Class
End Namespace

En este ejemplo, el código inspecciona la propiedad ReasonSessionEnding para determinar cómo finaliza la sesión de Windows. Usa este valor para mostrar un mensaje de confirmación al usuario. Si el usuario no quiere que la sesión finalice, el código establece Cancel en true para evitar que finalice la sesión de Windows.

Nota

No se genera el evento SessionEnding para aplicaciones XBAP.

Salir

Cuando una aplicación se apaga, es posible que necesite realizar algunos últimos procesos, como conservar el estado de la aplicación. Para estas situaciones, puede controlar el evento Exit, como hace el controlador de eventos App_Exit en el ejemplo siguiente. Se define como un controlador de eventos en el archivo App.xaml. Su implementación se resalta en los archivos App.xaml.cs y Application.xaml.vb.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App"
    StartupUri="MainWindow.xaml" 
    Startup="App_Startup" 
    Exit="App_Exit">
    <Application.Resources>
        <SolidColorBrush x:Key="ApplicationScopeResource" Color="White"></SolidColorBrush>
    </Application.Resources>
</Application>
using System.Windows;
using System.IO;
using System.IO.IsolatedStorage;

namespace SDKSample
{
    public partial class App : Application
    {
        string filename = "App.txt";

        public App()
        {
            // Initialize application-scope property
            this.Properties["NumberOfAppSessions"] = 0;
        }

        private void App_Startup(object sender, StartupEventArgs e)
        {
            // Restore application-scope property from isolated storage
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForDomain();
            try
            {
                using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filename, FileMode.Open, storage))
                using (StreamReader reader = new StreamReader(stream))
                {
                    // Restore each application-scope property individually
                    while (!reader.EndOfStream)
                    {
                        string[] keyValue = reader.ReadLine().Split(new char[] {','});
                        this.Properties[keyValue[0]] = keyValue[1];
                    }
                }
            }
            catch (FileNotFoundException ex)
            {
                // Handle when file is not found in isolated storage:
                // * When the first application session
                // * When file has been deleted
            }
        }

        private void App_Exit(object sender, ExitEventArgs e)
        {
            // Persist application-scope property to isolated storage
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForDomain();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filename, FileMode.Create, storage))
            using (StreamWriter writer = new StreamWriter(stream))
            {
                // Persist each application-scope property individually
                foreach (string key in this.Properties.Keys)
                {
                    writer.WriteLine("{0},{1}", key, this.Properties[key]);
                }
            }
        }
    }
}
Imports System.IO
Imports System.IO.IsolatedStorage

Namespace SDKSample
    Partial Public Class App
        Inherits Application
        Private filename As String = "App.txt"

        Public Sub New()
            ' Initialize application-scope property
            Me.Properties("NumberOfAppSessions") = 0
        End Sub

        Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
            ' Restore application-scope property from isolated storage
            Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForDomain()
            Try
                Using stream As New IsolatedStorageFileStream(filename, FileMode.Open, storage)
                Using reader As New StreamReader(stream)
                    ' Restore each application-scope property individually
                    Do While Not reader.EndOfStream
                        Dim keyValue() As String = reader.ReadLine().Split(New Char() {","c})
                        Me.Properties(keyValue(0)) = keyValue(1)
                    Loop
                End Using
                End Using
            Catch ex As FileNotFoundException
                ' Handle when file is not found in isolated storage:
                ' * When the first application session
                ' * When file has been deleted
            End Try
        End Sub

        Private Sub App_Exit(ByVal sender As Object, ByVal e As ExitEventArgs)
            ' Persist application-scope property to isolated storage
            Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForDomain()
            Using stream As New IsolatedStorageFileStream(filename, FileMode.Create, storage)
            Using writer As New StreamWriter(stream)
                ' Persist each application-scope property individually
                For Each key As String In Me.Properties.Keys
                    writer.WriteLine("{0},{1}", key, Me.Properties(key))
                Next key
            End Using
            End Using
        End Sub
    End Class
End Namespace

Para obtener el ejemplo completo, vea Conservar y restaurar propiedades en el ámbito de aplicación a través de sesiones de aplicación.

El evento Exit puede controlarse tanto por las aplicaciones independientes como por aplicaciones XBAP. En el caso de aplicaciones XBAP, se genera el evento Exit en las circunstancias siguientes:

  • Cuando se navega fuera de una aplicación XBAP.

  • En Internet Explorer, cuando se cierra la pestaña en la que se hospeda la aplicación XBAP.

  • Cuando se cierra el explorador.

Código de salida

La mayoría de las aplicaciones las inicia el sistema operativo en respuesta a una solicitud del usuario. En cambio, una aplicación puede ser iniciada por otra aplicación para realizar alguna tarea concreta. Cuando la aplicación iniciada se cierra, es posible que la aplicación que la ha iniciado quiera conocer la condición en la que se cerró la aplicación iniciada. En estas situaciones, Windows permite que las aplicaciones devuelvan un código de salida al cerrarse. De manera predeterminada, las aplicaciones WPF devuelven 0 como valor de código de salida.

Nota

Cuando se depura desde Visual Studio, el código de salida de la aplicación se muestra en la ventana de salida cuando se cierra la aplicación, en un mensaje similar al siguiente:

The program '[5340] AWPFApp.vshost.exe: Managed' has exited with code 0 (0x0).

Para abrir la ventana de salida, haga clic en Resultados en el menú Ver.

Para cambiar el código de salida, puede llamar a la sobrecarga Shutdown(Int32), que acepta un argumento de tipo entero como código de salida:

// Shutdown and return a non-default exit code
Application.Current.Shutdown(-1);
' Shutdown and return a non-default exit code
Application.Current.Shutdown(-1)

Para detectar el valor del código de salida y cambiarlo, controle el evento Exit. Al controlador de eventos Exit se le pasa un objeto ExitEventArgs que proporciona acceso al código de salida con la propiedad ApplicationExitCode. Para obtener más información, vea Exit.

Nota

El código de salida puede establecerse tanto en las aplicaciones independientes como en aplicaciones XBAP. En cambio, el valor del código de salida se omite para aplicaciones XBAP.

Excepciones no controladas

A veces, puede que una aplicación se cierre en condiciones irregulares, como cuando se produce una excepción imprevista. En este caso, es posible que la aplicación no tenga el código necesario para detectar y procesar la excepción. Este tipo de excepción es una excepción no controlada; se muestra una notificación similar a la que aparece en la figura siguiente antes de que se cierre la aplicación.

Captura de pantalla que muestra una notificación de excepción no controlada.

Desde la perspectiva del usuario, es mejor que una aplicación evite este comportamiento predeterminado realizando todas o alguna de las siguientes acciones:

  • Mostrar información fácil de usar.

  • Intentar mantener la aplicación en funcionamiento.

  • Registrar en el registro de eventos de Windows información detallada sobre la excepción que sea fácil de usar para el desarrollador.

La implementación de esta compatibilidad depende de la capacidad para detectar las excepciones no controladas; el evento DispatcherUnhandledException se genera con esta finalidad.

<Application
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.App"
  StartupUri="MainWindow.xaml"
  DispatcherUnhandledException="App_DispatcherUnhandledException" />
using System.Windows;
using System.Windows.Threading;

namespace SDKSample
{
    public partial class App : Application
    {
        void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            // Process unhandled exception

            // Prevent default unhandled exception processing
            e.Handled = true;
        }
    }
}
Imports System.Windows
Imports System.Windows.Threading

Namespace SDKSample
    Partial Public Class App
        Inherits Application
        Private Sub App_DispatcherUnhandledException(ByVal sender As Object, ByVal e As DispatcherUnhandledExceptionEventArgs)
            ' Process unhandled exception

            ' Prevent default unhandled exception processing
            e.Handled = True
        End Sub
    End Class
End Namespace

Al controlador de eventos DispatcherUnhandledException se le pasa un parámetro DispatcherUnhandledExceptionEventArgs que contiene información contextual referente a la excepción no controlada, incluida la propia excepción (DispatcherUnhandledExceptionEventArgs.Exception). Puede usar esta información para determinar cómo debe controlar la excepción.

Cuando controle DispatcherUnhandledException, establezca la propiedad DispatcherUnhandledExceptionEventArgs.Handled en true; de lo contrario, WPF seguirá considerando la excepción como no controlada y volverá al comportamiento predeterminado que se ha descrito anteriormente. Si se produce una excepción no controlada y no se controla el evento DispatcherUnhandledException, o bien, se controla el evento y se establece Handled en false, la aplicación se cerrará inmediatamente. Además, no se generará ningún otro evento Application. Por consiguiente, deberá controlar DispatcherUnhandledException si la aplicación tiene código que deba ejecutarse antes de que se cierre la aplicación.

Aunque es posible que una aplicación se cierre como resultado de una excepción no controlada, las aplicaciones suelen cerrarse en respuesta a una solicitud del usuario, tal como se explica en la sección siguiente.

Eventos de duración de la aplicación

Las aplicaciones independientes y XBAP no tienen exactamente la misma duración. En la ilustración siguiente se muestran los eventos clave en la duración de una aplicación independiente y la secuencia en la que se generan.

Aplicación independiente: eventos de objeto de la aplicación

Igualmente, en la figura siguiente se muestran los eventos clave a lo largo de la duración de una aplicación XBAP y la secuencia en la que se generan.

XBAP: eventos de objeto de la aplicación

Vea también