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 atributox:Class
. Cuando se compila la aplicación, la existencia dex:Class
en el archivo de marcación provoca que MSBuild cree una clasepartial
que deriva de Application y tiene el nombre especificado por el atributox: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 atributox:Class
en el marcado y debe derivarse de Application. Esto permite que el archivo de código subyacente se asocie a la clasepartial
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 para funcionar, como Internet Explorer y versiones anteriores de Firefox. Estos exploradores anteriores no suelen 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. Para más información, consulte Preguntas más frecuentes acerca de las aplicaciones hospedadas en explorador (XBAP) de WPF.
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 static
Current.
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.
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.
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.
Vea también
.NET Desktop feedback