Condividi tramite


Panoramica della gestione delle applicazioni

Tutte le applicazioni tendono a condividere un set comune di funzionalità che si applicano all'implementazione e alla gestione delle applicazioni. In questo argomento viene fornita una panoramica delle funzionalità della classe Application per la creazione e la gestione delle applicazioni.

La Classe Application

In WPF, la funzionalità comune a livello di applicazione viene incapsulata nella classe Application. La classe Application include le funzionalità seguenti:

  • Rilevamento e interazione con il ciclo di vita dell'applicazione.

  • Recupero ed elaborazione dei parametri della riga di comando.

  • Rilevamento e risposta a eccezioni non gestite.

  • Condivisione di proprietà e risorse dell'ambito dell'applicazione.

  • Gestione delle finestre nelle applicazioni autonome.

  • Rilevamento e gestione della navigazione.

Come eseguire attività comuni usando la classe application

Se non si è interessati a tutti i dettagli della classe Application, nella tabella seguente sono elencate alcune delle attività comuni per Application e come eseguirle. Visualizzando l'API e gli argomenti correlati, è possibile trovare altre informazioni e codice di esempio.

Compito Avvicinarsi
Ottenere un oggetto che rappresenta l'applicazione corrente Utilizzare la proprietà Application.Current.
Aggiungere una schermata di avvio a un'applicazione Vedere Aggiungere una schermata iniziale a un'applicazione WPF.
Avviare un'applicazione Usare il metodo Application.Run.
Chiudere un'applicazione Utilizzare il metodo Shutdown dell'oggetto Application.Current.
Ottenere argomenti dalla riga di comando Gestire l'evento Application.Startup e utilizzare la proprietà StartupEventArgs.Args. Per un esempio, vedi l'evento Application.Startup.
Ottenere e impostare il codice di uscita dell'applicazione Impostare la proprietà ExitEventArgs.ApplicationExitCode nel gestore eventi Application.Exit oppure chiamare il metodo Shutdown e passare un numero intero.
Rilevare e rispondere a eccezioni non gestite Gestire l'evento DispatcherUnhandledException.
Ottenere e impostare risorse con ambito applicazione Utilizzare la proprietà Application.Resources.
Usare un dizionario risorse con ambito applicazione Vedere Usare un dizionario risorse Application-Scope.
Accedere e impostare le proprietà con ambito dell'applicazione Utilizzare la proprietà Application.Properties.
Ottenere e salvare lo stato di un'applicazione Consulta Persistenza e ripristino delle proprietà Application-Scope nelle sessioni dell'applicazione.
Gestire file di dati non di codice, inclusi file di risorse, file di contenuto e file di origine del sito. Consulta la risorsa applicazione WPF, contenuto e file di dati .
Gestire le finestre nelle applicazioni autonome Consulta la panoramica di Windows WPF .
Tenere traccia e gestire la navigazione Consulta la panoramica della navigazione .

Definizione dell'applicazione

Per usare la funzionalità della classe Application, è necessario implementare una definizione dell'applicazione. Una definizione di applicazione WPF è una classe che deriva da Application ed è configurata con un'impostazione msbuild speciale.

Implementazione di una definizione di applicazione

Una tipica definizione di applicazione WPF viene implementata usando sia markup che code-behind. In questo modo è possibile usare il markup per impostare in modo dichiarativo le proprietà, le risorse e registrare gli eventi, gestendo gli eventi e implementando un comportamento specifico dell'applicazione nel code-behind.

L'esempio seguente illustra come implementare una definizione di applicazione usando sia markup che code-behind:

<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

Per consentire il funzionamento di un file di markup e di un file code-behind, è necessario eseguire le operazioni seguenti:

  • Nel markup, l'elemento Application deve includere l'attributo x:Class. Quando l'applicazione viene compilata, l'esistenza di x:Class nel file di markup fa sì che MSBuild crei una classe partial che deriva da Application e abbia il nome specificato dall'attributo x:Class. Ciò richiede di aggiungere una dichiarazione dello spazio dei nomi XML per lo schema XAML (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml").

  • Nel code-behind, la classe deve essere una classe partial con lo stesso nome specificato dall'attributo x:Class nel markup e deve derivare da Application. In questo modo il file code-behind può essere associato alla classe partial generata per il file di markup quando l'applicazione viene compilata (vedere Compilazione di un'applicazione WPF).

Nota

Quando si crea un nuovo progetto applicazione WPF o un progetto applicazione browser WPF con Visual Studio, per impostazione predefinita viene inclusa una definizione dell'applicazione e viene definita usando sia markup che code-behind.

Questo codice è il minimo necessario per implementare una definizione di applicazione. Tuttavia, è necessario creare una configurazione MSBuild aggiuntiva alla definizione dell'applicazione prima di compilare ed eseguire l'applicazione.

Configurazione della definizione dell'applicazione per MSBuild

Le applicazioni autonome e le applicazioni browser XAML (XBAP) richiedono l'implementazione di un determinato livello di infrastruttura prima che possano essere eseguite. La parte più importante di questa infrastruttura è il punto di ingresso. Quando un'applicazione viene avviata da un utente, il sistema operativo chiama il punto di ingresso, che è una funzione nota per l'avvio delle applicazioni.

Avvertimento

Per funzionare, gli XBAP richiedono browser legacy, come Internet Explorer e versioni precedenti di Firefox. Questi browser meno recenti sono in genere non supportati in Windows 10 e Windows 11. I browser moderni non supportano più la tecnologia necessaria per le app XBAP a causa di rischi per la sicurezza. I plug-in che abilitano XBAP non sono più supportati. Per altre informazioni, vedere domande frequenti sulle applicazioni WPF ospitate dal browser (XBAP).

Tradizionalmente, gli sviluppatori hanno bisogno di scrivere alcuni o tutto questo codice per se stessi, a seconda della tecnologia. Tuttavia, WPF genera automaticamente questo codice quando il file di markup della definizione dell'applicazione è configurato come elemento msbuild ApplicationDefinition, come illustrato nel file di progetto MSBuild seguente:

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

Poiché il file code-behind contiene codice, viene contrassegnato come elemento Compile MSBuild, come di consueto.

L'applicazione di queste configurazioni MSBuild ai file di markup e code-behind di una definizione di applicazione fa sì che MSBuild generi codice simile al seguente:

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

Il codice risultante arricchisce la definizione dell'applicazione con codice infrastrutturale aggiuntivo, che include il metodo entry-point Main. L'attributo STAThreadAttribute viene applicato al metodo Main per indicare che il thread dell'interfaccia utente principale per l'applicazione WPF è un thread STA, necessario per le applicazioni WPF. Quando viene chiamato, Main crea una nuova istanza di App prima di chiamare il metodo InitializeComponent per registrare gli eventi e impostare le proprietà implementate nel markup. Poiché InitializeComponent viene generato automaticamente, non è necessario chiamare in modo esplicito InitializeComponent da una definizione di applicazione come per le implementazioni di Page e Window. Infine, viene chiamato il metodo Run per avviare l'applicazione.

Recupero dell'applicazione corrente

Poiché la funzionalità della classe Application viene condivisa in un'applicazione, può essere presente una sola istanza della classe Application per ogni AppDomain. Per farlo, la classe Application viene implementata come classe singleton (vedere Implementazione di Singleton in C#), creando una singola istanza di se stessa e fornendo un accesso condiviso con la proprietà staticCurrent.

Nel codice seguente viene illustrato come acquisire un riferimento all'oggetto Application per l'oggetto corrente AppDomain.

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

Current restituisce un riferimento a un'istanza della classe Application. Se desideri un riferimento alla classe derivata Application, devi eseguire il cast del valore della proprietà Current, come illustrato nell'esempio seguente.

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

È possibile esaminare il valore di Current in qualsiasi momento della durata di un oggetto Application. Tuttavia, dovresti stare attento. Dopo la creazione di un'istanza della classe Application, si verifica un periodo durante il quale lo stato dell'oggetto Application è incoerente. Durante questo periodo, Application esegue le varie attività di inizializzazione richieste dal codice per l'esecuzione, tra cui la definizione dell'infrastruttura dell'applicazione, l'impostazione delle proprietà e la registrazione di eventi. Se si tenta di usare l'oggetto Application durante questo periodo, il codice potrebbe avere risultati imprevisti, in particolare se dipende dalle varie proprietà Application impostate.

Quando Application completa il lavoro di inizializzazione, la sua durata inizia davvero.

Durata dell'applicazione

Il ciclo di vita di un'applicazione WPF è contrassegnato da diversi eventi generati da Application per informarti quando l'applicazione è avviata, attivata, disattivata e arrestata.

Schermata iniziale

A partire da .NET Framework 3.5 SP1, è possibile specificare un'immagine da usare in una finestra di avvio o schermata iniziale. La classe SplashScreen semplifica la visualizzazione di una finestra di avvio durante il caricamento dell'applicazione. La finestra di SplashScreen viene creata e visualizzata prima di chiamare Run. Per altre informazioni, vedere ora di avvio dell'applicazione e Aggiungere una schermata iniziale a un'applicazione WPF.

Avvio di un'applicazione

Dopo che Run viene chiamato e l'applicazione viene inizializzata, l'applicazione è pronta per l'esecuzione. Questo momento è indicato quando viene generato l'evento Startup:

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>

A questo punto della durata di un'applicazione, la cosa più comune da eseguire consiste nello mostrare un'interfaccia utente.

Visualizzazione di un'interfaccia utente

La maggior parte delle applicazioni Windows autonome visualizza un Window quando iniziano a funzionare. Il gestore eventi Startup è una posizione da cui è possibile eseguire questa operazione, come illustrato nel codice seguente.

<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

Il primo Window creato in un'applicazione autonoma viene automaticamente impostato come finestra principale dell'applicazione per impostazione predefinita. Questo oggetto Window fa riferimento alla proprietà Application.MainWindow. Il valore della proprietà MainWindow può essere modificato a livello di codice se una finestra diversa dalla prima Window creata deve essere la finestra principale.

Quando un XBAP viene avviato, è molto probabile che venga reindirizzato a un Page. Questo è illustrato nel codice seguente.

<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

Se gestisci Startup solo per aprire un Window o navigare a un Page, puoi impostare l'attributo StartupUri direttamente nel markup.

Nell'esempio seguente viene illustrato come usare il StartupUri da un'applicazione autonoma per aprire un Window.

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

Nell'esempio seguente viene illustrato come usare StartupUri da un XBAP per passare a un Page.

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

Questo markup ha lo stesso effetto del codice precedente per l'apertura di una finestra.

Nota

Per ulteriori informazioni sulla navigazione, vedere Panoramica della navigazione.

È necessario gestire l'evento Startup per aprire un Window se è necessario crearne un'istanza usando un costruttore senza parametri oppure è necessario impostarne le proprietà o sottoscrivere i relativi eventi prima di visualizzarlo oppure è necessario elaborare eventuali argomenti della riga di comando forniti al momento dell'avvio dell'applicazione.

Elaborazione di argomenti Command-Line

In Windows le applicazioni autonome possono essere avviate da un prompt dei comandi o dal desktop. In entrambi i casi, gli argomenti della riga di comando possono essere passati all'applicazione. L'esempio seguente mostra un'applicazione che viene avviata con un singolo argomento della riga di comando, "/StartMinimized":

wpfapplication.exe /StartMinimized

Durante l'inizializzazione dell'applicazione, WPF recupera gli argomenti della riga di comando dal sistema operativo e li passa al gestore eventi Startup tramite la proprietà Args del parametro StartupEventArgs. È possibile recuperare e archiviare gli argomenti della riga di comando usando codice simile al seguente.

<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

Il codice controlla Startup per verificare se il parametro della riga di comando /StartMinimized è presente; se presente, apre la finestra principale con un WindowState di Minimized. Si noti che poiché la proprietà WindowState deve essere impostata a livello di codice, il Window principale deve essere aperto in modo esplicito nel codice.

Gli XBAP non possono recuperare ed elaborare gli argomenti della riga di comando perché vengono avviati tramite la distribuzione ClickOnce (vedere Distribuzione di un'applicazione WPF). Tuttavia, possono recuperare ed elaborare i parametri della stringa di query dagli URL usati per avviarli.

Attivazione e disattivazione dell'applicazione

Windows consente agli utenti di passare da un'applicazione all'altra. Il modo più comune consiste nell'usare la combinazione di tasti ALT+TAB. Un'applicazione può essere cambiata solo se ha un Window visibile che un utente può selezionare. L'Window attualmente selezionata è la finestra attiva (nota anche come finestra di primo piano ) ed è il Window che riceve l'input dell'utente. L'applicazione con la finestra attiva è l'applicazione attiva (o l'applicazione in primo piano ). Un'applicazione diventa l'applicazione attiva nelle circostanze seguenti:

  • Viene avviato e mostra un Window.

  • Un utente passa da un'altra applicazione selezionando un Window nell'applicazione.

È possibile rilevare quando un'applicazione diventa attiva gestendo l'evento Application.Activated.

Analogamente, un'applicazione può diventare inattiva nelle circostanze seguenti:

  • Un utente passa a un'altra applicazione da quella corrente.

  • Quando l'applicazione viene arrestata.

È possibile rilevare quando un'applicazione diventa inattiva gestendo l'evento Application.Deactivated.

Il codice seguente illustra come gestire gli eventi Activated e Deactivated per determinare se un'applicazione è attiva.

<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 Window può anche essere attivato e disattivato. Per altre informazioni, vedere Window.Activated e Window.Deactivated.

Nota

Application.ActivatedApplication.Deactivated vengono generati per gli XBAP.

Arresto dell'applicazione

La durata di un'applicazione termina quando viene arrestata, che può verificarsi per i motivi seguenti:

  • Un utente chiude ogni Window.

  • Un utente chiude il Windowprincipale.

  • Un utente termina la sessione su Windows disconnettendosi o arrestando il sistema.

  • È stata soddisfatta una condizione specifica dell'applicazione.

Per gestire l'arresto dell'applicazione, Application fornisce il metodo Shutdown, la proprietà ShutdownMode e gli eventi SessionEnding e Exit.

Nota

Shutdown può essere chiamato solo dalle applicazioni con UIPermission. Le applicazioni WPF autonome hanno sempre questa autorizzazione. Tuttavia, gli XBAP in esecuzione nella sandbox di sicurezza a fiducia parziale nell'area Internet non lo fanno.

Modalità di spegnimento

La maggior parte delle applicazioni viene arrestata quando tutte le finestre vengono chiuse o quando la finestra principale viene chiusa. In alcuni casi, tuttavia, altre condizioni specifiche dell'applicazione possono determinare quando un'applicazione viene arrestata. È possibile specificare le condizioni in cui l'applicazione verrà arrestata impostando ShutdownMode con uno dei valori di enumerazione ShutdownMode seguenti:

Il valore predefinito di ShutdownMode è OnLastWindowClose, il che significa che un'applicazione viene arrestata automaticamente quando l'ultima finestra nell'applicazione viene chiusa dall'utente. Tuttavia, se l'applicazione deve essere arrestata quando la finestra principale viene chiusa, WPF esegue automaticamente questa operazione se si imposta ShutdownMode su OnMainWindowClose. Questo è illustrato nell'esempio seguente.

<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" />

Quando si dispone di condizioni di arresto specifiche dell'applicazione, si imposti ShutdownMode su OnExplicitShutdown. In questo caso, è responsabilità dell'utente arrestare un'applicazione chiamando in modo esplicito il metodo Shutdown; in caso contrario, l'applicazione continuerà a essere in esecuzione anche se tutte le finestre sono chiuse. Si noti che Shutdown viene chiamato in modo implicito quando il ShutdownMode è OnLastWindowClose o OnMainWindowClose.

Nota

ShutdownMode può essere impostato da un XBAP, ma viene ignorato; un XBAP viene sempre arrestato quando si naviga lontano da esso in un browser o quando il browser che ospita l'XBAP viene chiuso. Per ulteriori informazioni, vedere la panoramica sulla navigazione .

Fine della sessione

Le condizioni di arresto descritte dalla proprietà ShutdownMode sono specifiche per un'applicazione. In alcuni casi, tuttavia, un'applicazione può chiudersi in seguito a una condizione esterna. La condizione esterna più comune si verifica quando un utente termina la sessione di Windows tramite le azioni seguenti:

  • Disconnessione

  • Spegnimento

  • Riavviare

  • Letargo

Per rilevare quando termina una sessione di Windows, è possibile gestire l'evento SessionEnding, come illustrato nell'esempio seguente.

<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

In questo esempio, il codice controlla la proprietà ReasonSessionEnding per determinare come termina la sessione di Windows. Usa questo valore per visualizzare un messaggio di conferma all'utente. Se l'utente non vuole che la sessione termini, il codice imposta Cancel su true per impedire la fine della sessione di Windows.

Nota

SessionEnding non viene generato per gli XBAP.

Uscita

Quando un'applicazione viene arrestata, potrebbe essere necessario eseguire un'elaborazione finale, ad esempio per rendere persistente lo stato dell'applicazione. Per queste situazioni, puoi gestire l'evento Exit, come fa il gestore dell'evento App_Exit nel seguente esempio. Viene definito come gestore di eventi nel file App.xaml. L'implementazione è evidenziata nei file App.xaml.cs e 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

Per l'esempio completo, vedere Conservare e ripristinare le proprietà Application-Scope attraverso le sessioni dell'applicazione.

Exit può essere gestito sia da applicazioni autonome che da XBAP. Per gli XBAP, Exit viene generato nelle seguenti circostanze:

  • Un XBAP viene spostato da.

  • In Internet Explorer, quando la scheda che ospita l'XBAP viene chiusa.

  • Quando il browser è chiuso.

Codice di uscita

Le applicazioni vengono avviate principalmente dal sistema operativo in risposta a una richiesta dell'utente. Tuttavia, un'applicazione può essere avviata da un'altra applicazione per eseguire alcune attività specifiche. Quando l'applicazione avviata viene arrestata, l'applicazione di avvio potrebbe voler conoscere la condizione in cui l'applicazione avviata viene arrestata. In queste situazioni, Windows consente alle applicazioni di restituire un codice di uscita dell'applicazione all'arresto. Per impostazione predefinita, le applicazioni WPF restituiscono un valore di codice di uscita pari a 0.

Nota

Quando si esegue il debug da Visual Studio, il codice di uscita dell'applicazione viene visualizzato nella finestra output quando l'applicazione viene arrestata, in un messaggio simile al seguente:

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

Si apre la finestra Output facendo clic su Output nel menu Visualizza.

Per modificare il codice di uscita, puoi chiamare l'overload Shutdown(Int32), che accetta un argomento intero come codice di uscita.

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

È possibile rilevare il valore del codice di uscita e modificarlo gestendo l'evento Exit. Il gestore eventi Exit riceve un ExitEventArgs che fornisce l'accesso al codice di uscita tramite la proprietà ApplicationExitCode. Per altre informazioni, vedere Exit.

Nota

È possibile impostare il codice di uscita sia nelle applicazioni autonome che negli XBAP. Tuttavia, il valore del codice di uscita viene ignorato per gli XBAP.

Eccezioni non gestite

A volte un'applicazione può bloccarsi in condizioni anomale, ad esempio quando viene generata un'eccezione imprevista. In questo caso, l'applicazione potrebbe non avere il codice per rilevare ed elaborare l'eccezione. Questo tipo di eccezione è un'eccezione non gestita; Una notifica simile a quella illustrata nella figura seguente viene visualizzata prima che l'applicazione venga chiusa.

Screenshot che mostra una notifica di eccezione non gestita.

Dal punto di vista dell'esperienza utente, è preferibile per un'applicazione evitare questo comportamento predefinito eseguendo alcune o tutte le operazioni seguenti:

  • Visualizzazione di informazioni intuitive.

  • Tentativo di mantenere un'applicazione attiva.

  • Registrazione di informazioni dettagliate sulle eccezioni facilmente comprensibili per gli sviluppatori nel registro eventi di Windows.

L'implementazione di questo supporto dipende dalla possibilità di rilevare le eccezioni non gestite, ovvero ciò per cui viene generato l'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

Al gestore dell'evento DispatcherUnhandledException viene passato un parametro DispatcherUnhandledExceptionEventArgs che contiene informazioni contestuali sull'eccezione non gestita, inclusa l'eccezione stessa (DispatcherUnhandledExceptionEventArgs.Exception). È possibile usare queste informazioni per determinare come gestire l'eccezione.

Quando si gestisce DispatcherUnhandledException, è necessario impostare la proprietà DispatcherUnhandledExceptionEventArgs.Handled su true; in caso contrario, WPF considera comunque l'eccezione non gestita e ripristina il comportamento predefinito descritto in precedenza. Se viene generata un'eccezione non gestita e l'evento DispatcherUnhandledException non viene gestito, oppure se l'evento è gestito e Handled è impostato su false, l'applicazione viene arrestata immediatamente. Inoltre, non vengono generati altri eventi Application. Di conseguenza, è necessario gestire DispatcherUnhandledException se l'applicazione dispone di codice che deve essere eseguito prima dell'arresto dell'applicazione.

Sebbene un'applicazione possa essere arrestata in seguito a un'eccezione non gestita, un'applicazione viene in genere arrestata in risposta a una richiesta utente, come descritto nella sezione successiva.

Eventi del ciclo di vita dell'applicazione

Le applicazioni autonome e gli XBAP non hanno esattamente le stesse durate. La figura seguente illustra gli eventi chiave nella durata di un'applicazione autonoma e mostra la sequenza in cui vengono generati.

Applicazione autonoma - Eventi dell'oggetto applicazione

Analogamente, la figura seguente illustra gli eventi chiave nel ciclo di vita di un XBAP e mostra la sequenza in cui vengono generati.

XBAP - Eventi dell'oggetto Application

Vedere anche