Compartir a través de


Introducción a la administración de aplicaciones

Todas las aplicaciones tienden a compartir un conjunto común de funcionalidades que se aplican a la implementación y administración de aplicaciones. En este tema se proporciona información general sobre la funcionalidad de la Application clase para crear y administrar aplicaciones.

La clase Application

En WPF, la funcionalidad común con ámbito de aplicación se encapsula en la Application clase . La Application clase incluye la siguiente funcionalidad:

  • Seguimiento e interacción con el ciclo de vida de la aplicación.

  • Recuperación y procesamiento de parámetros de línea de comandos.

  • Detección y respuesta a excepciones no controladas.

  • Uso compartido de propiedades y recursos del ámbito de la aplicación.

  • Administración de ventanas en aplicaciones independientes.

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

Cómo realizar tareas comunes mediante la clase Application

En caso de que no le interesen todos los detalles de la Application clase, la tabla siguiente enumera algunas tareas comunes para Application y cómo llevarlas a cabo. Al ver la API y los temas relacionados, puede encontrar más información y código de ejemplo.

Tarea Enfoque
Obtener un objeto que representa la aplicación actual Use la propiedad Application.Current.
Agregar una pantalla de inicio a una aplicación Consulte Agregar una pantalla de presentación a una aplicación WPF.
Inicio de una aplicación Use el método Application.Run.
Detener una aplicación Utilice el Shutdown método del Application.Current objeto .
Obtención de argumentos de la línea de comandos Controle el Application.Startup evento y use la StartupEventArgs.Args propiedad . Para obtener un ejemplo, vea el Application.Startup evento .
Obtener y establecer el código de salida de la aplicación Establezca la ExitEventArgs.ApplicationExitCode propiedad en el Application.Exit controlador de eventos o llame al Shutdown método y pase un entero.
Detección y respuesta a excepciones no controladas Controle el evento DispatcherUnhandledException.
Obtención y establecimiento de recursos con ámbito de aplicación Use la propiedad Application.Resources.
Uso de un diccionario de recursos de ámbito de aplicación Consulte Utilizar un diccionario de recursos Application-Scope.
Obtener y establecer propiedades con ámbito de aplicación Use la propiedad Application.Properties.
Obtener y guardar el estado de una aplicación Consulte Persist and Restore Application-Scope properties across Application Sessions (Conservar y restaurar propiedades de Application-Scope entre sesiones de aplicación).
Administre 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. Consulte Recursos, contenido y archivos de datos de aplicaciones de WPF.
Administrar ventanas en aplicaciones independientes Consulte Información general sobre Windows de WPF.
Seguimiento y administración de la navegación Consulte Información general de navegación.

Definición de la aplicación

Para usar la funcionalidad de la Application clase , 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 una configuración especial de MSBuild.

Implementación de una definición de aplicación

Una definición típica de la aplicación WPF se implementa mediante marcado y código subyacente. Esto le permite usar el marcado para establecer mediante declaración propiedades de aplicación, recursos y registrar eventos, a la vez que controla los eventos e implementa el comportamiento específico de la aplicación en el código subyacente.

En el ejemplo siguiente se muestra cómo implementar una definición de aplicación mediante marcado y 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 permitir que un archivo de marcado y un archivo de código subyacente funcionen conjuntamente, es necesario que se produzca 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 marcado hace que MSBuild cree una clase partial que deriva de Application y tenga el nombre especificado por el atributo x:Class. Esto requiere la adición de 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 partial debe tener el mismo nombre especificado por el atributo x:Class en el marcado y debe derivar de Application. Esto permite asociar el archivo de código subyacente a la partial clase que se genera para el archivo de marcado cuando se compila la aplicación (vea Building a WPF Application).

Nota:

Al crear un nuevo proyecto de aplicación WPF o un proyecto de aplicación de explorador WPF mediante Visual Studio, se incluye una definición de aplicación de forma predeterminada y se define mediante marcado y código subyacente.

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

Configuración de la definición de aplicación para MSBuild

Las aplicaciones independientes y las aplicaciones de explorador XAML (XBAP) requieren la implementación de un determinado nivel de infraestructura para poder ejecutarlas. 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 aplicaciones.

Advertencia

Los XBAP requieren que los exploradores heredados funcionen, como Internet Explorer y versiones anteriores de Firefox. Normalmente, estos exploradores más antiguos no son 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. Para obtener más información, vea Preguntas más frecuentes sobre las aplicaciones hospedadas por el explorador (XBAP) de WPF.

Tradicionalmente, los desarrolladores han necesitado escribir parte o todo este código para sí mismos, en función de la tecnología. Sin embargo, WPF genera este código automáticamente cuando el archivo de marcado de la definición de la aplicación está configurado como un elemento de MSBuild, como se muestra en el siguiente archivo de proyecto de MSBuild ApplicationDefinition :

<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 de MSBuild Compile , como es normal.

La aplicación de estas configuraciones de MSBuild a los archivos de marcado y código subyacente 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 aumenta la definición de la aplicación con código de infraestructura adicional, que incluye el método Mainde punto de entrada . El STAThreadAttribute atributo se aplica al Main método para indicar que el subproceso principal de la interfaz de usuario de la aplicación WPF es un subproceso STA, que es necesario para las aplicaciones WPF. Cuando se llama a 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 InitializeComponent se genera automáticamente, no necesitas llamar explícitamente a InitializeComponent desde una definición de aplicación, como sí debes hacerlo para las implementaciones de Page y Window. Por último, el método Run se llama para iniciar la aplicación.

Obtención de la aplicación actual

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

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

// 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 Application clase . Si desea una referencia a su clase derivada Application, debe hacer un casting del 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 momento de la vida útil de un objeto Application. No obstante, debes tener cuidado. Una vez creada la instancia de la Application clase, hay un período durante el cual el estado del Application objeto es incoherente. Durante este período, Application realiza las distintas tareas de inicialización que requiere el código para ejecutarse, incluido el establecimiento de la infraestructura de la aplicación, la configuración de propiedades y el registro de eventos. Si intenta usar el Application objeto durante este período, el código puede tener resultados inesperados, especialmente si depende de las distintas Application propiedades que se establecen.

Cuando Application completa su trabajo de inicialización, su ciclo de vida comienza realmente.

Duración de la aplicación

La duración de una aplicación WPF está marcada por varios eventos que son generados por Application para informarle de cuándo se ha iniciado, se ha activado, se ha desactivado y se ha cerrado la aplicación.

Pantalla de presentación

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

Iniciar una aplicación

Después de que se llama a Run y se inicializa la aplicación, esta está lista para ejecutarse. Este momento se indica cuando el evento Startup es generado:

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 momento de la duración de una aplicación, lo más común es mostrar una interfaz de usuario.

Mostrar una interfaz de usuario

La mayoría de las aplicaciones windows independientes abren una Window cuando comienzan a ejecutarse. El Startup controlador de eventos es una ubicación desde la que puede hacerlo, 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:

La primera Window en una aplicación independiente se convierte en la ventana principal de la aplicación de forma predeterminada. Este Window objeto es referenciado por la propiedad Application.MainWindow. El valor de la MainWindow propiedad se puede cambiar mediante programación si una ventana diferente a la primera instancia Window debe ser la ventana principal.

Cuando un XBAP se inicia por primera vez, lo más probable es que navegue a un 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 maneja Startup solo para abrir un Window o navegar a un Page, puede establecer el atributo StartupUri en el marcado.

El siguiente ejemplo muestra cómo usar la StartupUri desde una aplicación independiente para abrir una Window.

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

En el ejemplo siguiente se muestra cómo usar StartupUri desde un XBAP para navegar a .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, consulte Información general sobre la navegación.

Debe controlar el Startup evento para abrir un Window si necesita crear instancias de él mediante un constructor sin parámetros, o bien debe establecer sus propiedades o suscribirse a sus eventos antes de mostrarlo, o bien debe procesar los argumentos de línea de comandos que se proporcionaron cuando se inició la aplicación.

Procesamiento de argumentos de Command-Line

En Windows, las aplicaciones independientes pueden ser ejecutadas desde un comando o desde el escritorio. En ambos casos, los argumentos de la línea de comandos se pueden pasar a la aplicación. En el ejemplo siguiente se muestra una aplicación que se inicia con un único argumento de línea de comandos, "/StartMinimized":

wpfapplication.exe /StartMinimized

Durante la Startup 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 a través de la Args propiedad del StartupEventArgs parámetro . Puede recuperar y almacenar los argumentos de la línea de comandos mediante 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 maneja Startup para verificar si se proporcionó el argumento de línea de comandos /StartMinimized; en caso afirmativo, abre la ventana principal con un WindowState de Minimized. Tenga en cuenta que, dado que la WindowState propiedad debe establecerse mediante programación, la principal Window debe abrirse explícitamente en el código.

XBAPs no puede recuperar ni procesar argumentos de la línea de comandos porque se inician mediante la implementación clickOnce (consulte Implementación de una aplicación WPF). Sin embargo, pueden recuperar y procesar parámetros de cadena de consulta de las direcciones URL que se usan para iniciarlos.

Activación y desactivación de aplicaciones

Windows permite a los usuarios cambiar entre aplicaciones. La manera más común es usar la combinación de teclas ALT+TAB. Una aplicación solo se puede conmutar si tiene un elemento visible Window que un usuario puede seleccionar. El Window actualmente seleccionado es la ventana activa, que también se conoce como ventana de primer plano, y es la Window que recibe la entrada del usuario. La aplicación con la ventana activa es la aplicación activa (o la aplicación en primer plano). Una aplicación se convierte en la aplicación activa en las siguientes circunstancias:

  • Se inicia y muestra un Window.

  • Un usuario cambia de otra aplicación seleccionando un Window elemento en la aplicación.

Puede detectar cuándo una aplicación se activa controlando el Application.Activated evento.

Del mismo modo, una aplicación puede estar inactiva en las siguientes circunstancias:

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

  • Cuando se cierra la aplicación.

Puede detectar cuándo una aplicación deja de estar inactiva controlando el Application.Deactivated evento.

En el código siguiente se muestra cómo controlar los Activated eventos 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

Window también se puede activar y desactivar. Consulte Window.Activated y Window.Deactivated para obtener más información.

Nota:

Ni ni Application.ActivatedApplication.Deactivated se generan para XBAP.

Apagado de la aplicación

La vida útil de una aplicación finaliza cuando se cierra, lo que puede ocurrir por los siguientes motivos:

  • Un usuario cierra cada Window.

  • Un usuario cierra el objeto principal Window.

  • Un usuario finaliza la sesión de Windows al cerrar sesión o apagar el sistema.

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

Para ayudarle a administrar el apagado de la aplicación, Application proporciona el Shutdown método, la ShutdownMode propiedad y los SessionEnding eventos y Exit .

Nota:

Shutdown solo se puede llamar desde aplicaciones que tienen UIPermission. Las aplicaciones WPF independientes siempre tienen este permiso. Sin embargo, los XBAP que se ejecutan en la zona de Internet, dentro de un entorno de seguridad de confianza parcial, no lo permiten.

Modo de apagado

La mayoría de las aplicaciones se apagan cuando se cierran todas las ventanas o cuando se cierra la ventana principal. A veces, sin embargo, otras condiciones específicas de la aplicación pueden determinar cuándo se cierra una aplicación. Puede especificar las condiciones en las que se apagará la aplicación estableciendo ShutdownMode uno de los siguientes ShutdownMode valores de enumeración:

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. Sin embargo, si su aplicación debe cerrarse cuando se cierra la ventana principal, WPF lo hace automáticamente si se 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" />

Cuando tenga condiciones de apagado específicas de la aplicación, ajuste ShutdownMode a OnExplicitShutdown. En este caso, es su responsabilidad cerrar una aplicación llamando explícitamente al Shutdown método ; de lo contrario, la aplicación seguirá ejecutándose incluso si todas las ventanas están cerradas. Tenga en cuenta que Shutdown se llama implícitamente cuando ShutdownMode es OnLastWindowClose o OnMainWindowClose.

Nota:

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

Finalización de la sesión

Las condiciones de apagado descritas por la ShutdownMode propiedad son específicas de una aplicación. Sin embargo, en algunos casos, una aplicación puede cerrarse como resultado de una condición externa. La condición externa más común se produce cuando un usuario finaliza la sesión de Windows mediante las siguientes acciones:

  • Cerrar sesión

  • Apagando

  • Reiniciar

  • Hibernando

Para detectar cuándo finaliza una sesión de Windows, puede controlar el SessionEnding evento, 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 ReasonSessionEnding propiedad 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 finalice la sesión, el código establece Cancel para true impedir que finalice la sesión de Windows.

Nota:

SessionEnding no se genera para XBAP.

Salir

Cuando una aplicación se cierra, es posible que tenga que realizar algún procesamiento final, como conservar el estado de la aplicación. En estas situaciones, puede controlar el Exit evento, como lo hace el App_Exit controlador de eventos 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, consulte Persist and Restore Application-Scope Properties Across Application Sessions.

Exit se puede gestionar mediante aplicaciones independientes y XBAP. En el caso de XBAPs, Exit se genera en las siguientes circunstancias:

  • Se abandona un XBAP.

  • En Internet Explorer, cuando se cierra la pestaña que hospeda el XBAP.

  • Cuando se cierra el explorador.

Código de salida

El sistema operativo inicia principalmente las aplicaciones en respuesta a una solicitud de usuario. Sin embargo, otra aplicación puede iniciar una aplicación para realizar alguna tarea específica. Cuando se cierra la aplicación iniciada, es posible que la aplicación de inicio quiera saber la condición con la que se cierra la aplicación iniciada. En estas situaciones, Windows permite a las aplicaciones devolver un código de salida de la aplicación al apagarse. De forma predeterminada, las aplicaciones WPF devuelven un valor de código de salida de 0.

Nota:

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

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

Para abrir la ventana Salida , haga clic en Salida en el menú Ver .

Para cambiar el código de salida, puede llamar a la Shutdown(Int32) sobrecarga, que acepta un argumento entero para que sea el 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)

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

Nota:

Puede establecer el código de salida en aplicaciones independientes y XBAP. Sin embargo, el valor del código de salida se omite para XBAP.

Excepciones no controladas

A veces, una aplicación puede cerrarse en condiciones anómalas, como cuando se produce una excepción imprevista. En este caso, es posible que la aplicación no tenga el código 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 se muestra en la ilustración siguiente antes de cerrar la aplicación.

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

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

  • Mostrar información fácil de usar.

  • Intentar mantener una aplicación en ejecución.

  • Registro de información detallada sobre excepciones amigable para desarrolladores en el registro de eventos de Windows.

La implementación de este soporte depende de poder detectar excepciones no controladas, que es para lo que se genera el evento DispatcherUnhandledException.

<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

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

Cuando maneje DispatcherUnhandledException, debe establecer la propiedad DispatcherUnhandledExceptionEventArgs.Handled a true; de lo contrario, WPF sigue considerando que la excepción no está gestionada y se revierte al comportamiento predeterminado descrito anteriormente. Si se produce una excepción no controlada y, o bien, el DispatcherUnhandledException evento no se controla, o el evento se controla y Handled se establece en false, la aplicación se cierra inmediatamente. Además, no se generan otros Application eventos. Por lo tanto, debe controlar DispatcherUnhandledException si la aplicación tiene código que debe ejecutarse antes de que se cierre la aplicación.

Aunque una aplicación puede apagarse como resultado de una excepción no controlada, una aplicación normalmente se cierra en respuesta a una solicitud de usuario, como se describe en la sección siguiente.

Eventos del ciclo de vida de la aplicación

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

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

Del mismo modo, la figura siguiente ilustra los eventos clave en el ciclo de vida de un XBAP y muestra la secuencia en la que se producen.

XBAP: eventos de objeto de aplicación

Consulte también