Übersicht über die Anwendungsverwaltung

Alle Anwendungen nutzen in der Regel einen gemeinsamen Satz von Funktionen, der für die Implementierung und Verwaltung der Anwendung gilt. Dieses Thema bietet eine Übersicht über die Funktionen in der Application-Klasse zum Erstellen und Verwalten von Anwendungen.

Die Application-Klasse

In WPF sind die allgemeinen anwendungsspezifischen Funktionen in der Application-Klasse gekapselt. Die Application-Klasse beinhaltet folgende Funktionen:

  • Lebensdauer der Anwendung nachverfolgen und mit ihr interagieren

  • Befehlszeilenparameter abrufen und verarbeiten

  • Nicht behandelte Ausnahmen erkennen und darauf reagieren

  • Anwendungsspezifische Eigenschaften und Ressourcen teilen

  • Fenster in eigenständigen Anwendungen verwalten

  • Navigation nachverfolgen und verwalten

Ausführen allgemeiner Aufgaben mithilfe der Application-Klasse

Wenn Sie nicht an allen Details der Application-Klasse interessiert sind, enthält die folgende Tabelle einige häufige Aufgaben für Application sowie Informationen zu ihrer Ausführung. Weitere Informationen und entsprechenden Beispielcode finden Sie über die zugehörigen APIs und Themen.

Aufgabe Vorgehensweise
Ein Objekt abrufen, das die aktuelle Anwendung darstellt. Verwenden Sie die Application.Current-Eigenschaft.
Einen Startbildschirm zu einer Anwendung hinzufügen. Weitere Informationen finden Sie unter Hinzufügen eines Begrüßungsbildschirms zu einer WPF-Anwendung.
Eine Anwendung starten. Sie verwenden die Application.Run-Methode.
Eine Anwendung beenden. Sie verwenden die Shutdown-Methode des Application.Current-Objekts.
Argumente über die Befehlszeile abrufen. Behandeln Sie das Application.Startup-Ereignis, und verwenden Sie die StartupEventArgs.Args-Eigenschaft. Ein Beispiel dafür finden Sie beim Application.Startup-Ereignis.
Exitcode der Anwendung abrufen und festlegen. Legen Sie die ExitEventArgs.ApplicationExitCode-Eigenschaft im Application.Exit-Ereignishandler fest, oder rufen Sie die Shutdown-Methode auf, und übergeben Sie eine ganze Zahl.
Nicht behandelte Ausnahmen erkennen und darauf reagieren. Behandeln Sie das DispatcherUnhandledException-Ereignis.
Anwendungsspezifische Ressourcen abrufen und festlegen. Verwenden Sie die Application.Resources-Eigenschaft.
Ein anwendungsspezifisches Ressourcenverzeichnis verwenden. Weitere Informationen finden Sie unter Verwenden eines Ressourcenverzeichnisses für den Anwendungsbereich.
Anwendungsspezifische Eigenschaften abrufen und festlegen. Verwenden Sie die Application.Properties-Eigenschaft.
Den Zustand einer Anwendung abrufen und speichern. Weitere Informationen finden Sie unter Beibehalten und Wiederherstellen von Eigenschaften für den Anwendungsbereich über mehrere Anwendungssitzungen.
Datendateien ohne Code verwalten, einschließlich Ressourcendateien, Inhalts- und Ursprungssitedateien. Weitere Informationen finden Sie unter WPF-Anwendungsressource, Inhalts- und Datendateien.
Fenster in eigenständigen Anwendungen verwalten. Weitere Informationen finden Sie unter Übersicht über WPF-Fenster.
Navigation überwachen und verwalten. Weitere Informationen finden Sie unter Übersicht über die Navigation.

Die Anwendungsdefinition

Damit Sie die Funktionen der Application-Klasse nutzen können, müssen Sie eine Anwendungsdefinition implementieren. Eine WPF-Anwendungsdefinition ist eine Klasse, die von Application abgeleitet und mit einer speziellen MSBuild-Einstellung konfiguriert ist.

Implementieren einer Anwendungsdefinition

Eine typische WPF-Anwendungsdefinition wird mithilfe von Markup und CodeBehind implementiert. Dadurch können Sie Anwendungseigenschaften und Ressourcen deklarativ mithilfe des Markups festlegen und Ereignisse registrieren, während mit CodeBehind Ereignisse behandelt und anwendungsspezifisches Verhalten implementiert wird.

Das folgende Beispiel veranschaulicht die Implementierung einer Anwendungsdefinition mithilfe von Markup und CodeBehind:

<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

Damit eine Markup- und eine CodeBehind-Datei zusammenarbeiten können, ist Folgendes erforderlich:

  • Im Markup muss das Application-Element das x:Class-Attribut enthalten. Beim Erstellen der Anwendung führt das Vorhandensein von x:Class in der Markupdatei dazu, dass MSBuild eine partial-Klasse erstellt, die von Application abgeleitet wird und den durch das x:Class-Attribut festgelegten Namen erhält. Dies erfordert das Hinzufügen einer XML-Namespacedeklaration für das XAML-Schema (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml").

  • Bei CodeBehind muss die Klasse eine partial-Klasse mit demselben Namen sein, der im Markup durch das x:Class-Attribut angegeben ist, und sie muss von Application abgeleitet sein. Auf diese Weise kann die CodeBehind-Datei mit der partial-Klasse verknüpft werden, die beim Erstellen der Anwendung (siehe Erstellen einer WPF-Anwendung) für die Markupdatei generiert wird.

Hinweis

Wenn Sie ein neues WPF-Anwendungsprojekt oder WPF-Browseranwendungsprojekt mit Visual Studio erstellen, ist standardmäßig eine Anwendungsdefinition enthalten, die mithilfe von Markup und CodeBehind definiert wurde.

Dieser Code ist die Mindestanforderung zum Implementieren einer Anwendungsdefinition. Es muss jedoch eine zusätzliche MSBuild-Konfiguration in der Anwendungsdefinition vorgenommen werden, bevor die Anwendung erstellt und ausgeführt werden kann.

Konfigurieren der Anwendungsdefinition für MSBuild

Damit eigenständige Anwendungen und XAML-Browseranwendungen (XBAPs) ausgeführt werden können, ist die Implementierung eines gewissen Maßes an Infrastruktur erforderlich. Der wichtigste Teil dieser Infrastruktur ist der Einstiegspunkt. Wenn eine Anwendung von einem Benutzer gestartet wird, ruft das Betriebssystem den Einstiegspunkt auf, der eine bekannte Funktion zum Starten von Anwendungen ist.

Warnung

XBAPs erfordern Legacybrowser, z. B. Internet Explorer und Firefox. Diese älteren Browserversionen werden unter Windows 10 und Windows 11 normalerweise nicht unterstützt. Moderne Browser unterstützen die für XBAP-Apps erforderliche Technologie aufgrund von Sicherheitsrisiken nicht mehr. Plug-Ins, die XBAPs aktivieren, werden nicht mehr unterstützt.

In der Vergangenheit mussten Entwickler je nach Technologie einen Teil oder sämtlichen Code selbst verfassen. Jedoch generiert WPF diesen Code für Sie, wenn die Markupdatei Ihrer Anwendungsdefinition als MSBuild-ApplicationDefinition-Element konfiguriert ist, wie in der folgenden MSBuild-Projektdatei veranschaulicht:

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

Da die CodeBehind-Datei Code enthält, ist sie normal als MSBuild-Compile-Element markiert.

Die Anwendung dieser MSBuild-Konfigurationen auf die Markup- und CodeBehind-Dateien einer Anwendungsdefinition führt dazu, dass MSBuild Code wie den folgenden generiert:

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

Der resultierende Code ergänzt die Anwendungsdefinition um zusätzlichen Infrastrukturcode, der die Einstiegspunktmethode Main enthält. Das STAThreadAttribute-Attribut wird auf die Main-Methode angewendet, um anzuzeigen, dass der Hauptthread der Benutzeroberfläche für die WPF-Anwendung ein STA-Thread und für WPF-Anwendungen erforderlich ist. Nach dem Aufruf von Main wird eine neue Instanz von App erstellt, bevor die InitializeComponent-Methode aufgerufen wird, um die Ereignisse zu registrieren und die Eigenschaften festzulegen, die im Markup implementiert sind. Da InitializeComponent für Sie generiert wird, müssen Sie InitializeComponent nicht explizit über eine Anwendungsdefinition wie für Page- und Window-Implementierungen aufrufen. Schließlich wird die Run-Methode aufgerufen, um die Anwendung zu starten.

Abrufen der aktuellen Anwendungsdomäne

Da die Funktionen der Application-Klasse innerhalb einer Anwendung durchgängig und gemeinsam genutzt werden, kann es nur eine Instanz der Application-Klasse pro AppDomain geben. Um dies zu erzwingen, wird die Application-Klasse als Singleton-Klasse implementiert (siehe Implementieren von Singleton in C#), die eine einzelne Instanz von sich selbst erstellt und mit der staticCurrent-Eigenschaft den gemeinsamen Zugriff auf sie bereitstellt.

Der folgende Code zeigt, wie ein Verweis auf das Application-Objekt für die aktuelle AppDomain abgerufen wird.

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

Current gibt einen Verweis auf eine Instanz der Application-Klasse zurück. Wenn Sie einen Verweis auf Ihre abgeleitete Application-Klasse benötigen, müssen Sie eine Typumwandlung des Werts der Current-Eigenschaft vornehmen, wie im folgenden Beispiel gezeigt.

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

Sie können den Wert von Current während der Lebensdauer eines Application-Objekts jederzeit untersuchen. Sie sollten dabei jedoch vorsichtig sein. Nach der Instanziierung der Application-Klasse gibt es einen Zeitraum, während dessen der Zustand des Application-Objekts inkonsistent ist. Während dieses Zeitraums führt Application verschiedene Initialisierungsaufgaben durch, die für die Ausführung Ihres Codes erforderlich sind, darunter die Einrichtung der Infrastruktur, das Festlegen von Eigenschaften und das Registrieren von Ereignissen. Wenn Sie versuchen, das Application-Objekt während dieses Zeitraums zu verwenden, führt der Code möglicherweise zu unerwarteten Ergebnissen. Dies gilt insbesondere, wenn er davon abhängig ist, dass verschiedene Application-Eigenschaften festgelegt sind.

Wenn Application seine Initialisierungsaufgabe abgeschlossen hat, beginnt seine Lebensdauer wirklich.

Anwendungslebensdauer

Die Lebensdauer einer WPF-Anwendung ist durch verschiedene Ereignisse gekennzeichnet, die von Application ausgelöst werden, damit Sie wissen, wann die Anwendung gestartet, aktiviert, deaktiviert und heruntergefahren wurde.

Begrüßungsbildschirm

Ab .NET Framework 3.5 SP1 können Sie ein Bild angeben, das in einem Startfenster oder auf dem Begrüßungsbildschirm verwendet wird. Dank der SplashScreen-Klasse gestaltet es sich einfach, ein Startfenster anzuzeigen, während die Anwendung geladen wird. Das SplashScreen-Fenster wird erstellt und angezeigt, bevor Run aufgerufen wird. Weitere Informationen finden Sie unter Anwendungsstartzeit und Hinzufügen eines Begrüßungsbildschirms zu einer WPF-Anwendung.

Starten einer Anwendung

Nachdem Run aufgerufen und die Anwendung initialisiert wurde, ist die Anwendung zur Ausführung bereit. Dieser Moment wird durch die Auslösung des Startup-Ereignisses angezeigt:

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>

An diesem Punkt der Lebensdauer einer Anwendung ist der am häufigsten verwendete Schritt das Anzeigen einer Benutzeroberfläche.

Anzeigen einer Benutzeroberfläche

Die meisten eigenständigen Windows-Anwendungen öffnen ein Window, wenn ihre Ausführung beginnt. Wie im folgenden Code veranschaulicht, stellt der Startup-Ereignishandler einen geeigneten Ausgangspunkt dafür dar.

<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

Hinweis

Das erste Window, das in einer eigenständigen Anwendung instanziiert werden soll, wird standardmäßig zum Hauptanwendungsfenster. Dieses Window-Objekt wird von der Application.MainWindow-Eigenschaft zurückgegeben. Der Wert der MainWindow-Eigenschaft kann programmgesteuert geändert werden, wenn ein anderes Fenster als das zuerst instanziierte Window das Hauptfenster sein soll.

Beim ersten Starten einer XBAP navigiert sie mit hoher Wahrscheinlichkeit zu einer Page. Dies wird im folgenden Code veranschaulicht.

<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

Wenn Sie Startup lediglich zum Öffnen eines Window oder zum Navigieren zu einer Page verarbeiten, können Sie stattdessen das StartupUri-Attribut in Markup festlegen.

Das folgende Beispiel zeigt, wie Sie den StartupUri von einer eigenständigen Anwendung verwenden, um ein Window zu öffnen.

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

Das folgende Beispiel zeigt, wie Sie den StartupUri einer XBAP verwenden, um zu einer Page zu navigieren.

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

Dieses Markup hat denselben Effekt wie der vorherige Code zum Öffnen eines Fensters.

Hinweis

Weitere Informationen zur Navigation finden Sie unter Übersicht über die Navigation.

Sie müssen das Startup-Ereignis behandeln, um ein Window zu öffnen, wenn Sie es mithilfe eines nicht parameterlosen Konstruktors instanziieren müssen. Oder Sie müssen die Eigenschaften festlegen bzw. Ereignisse abonnieren, bevor Sie das Fenster anzeigen. Sie können aber auch alle Befehlszeilenargumente verarbeiten, die beim Starten der Anwendung übergeben wurden.

Verarbeiten von Befehlszeilenargumenten

In Windows können eigenständige Anwendungen über eine Eingabeaufforderung oder auf dem Desktop gestartet werden. In beiden Fällen können Befehlszeilenargumente an die Anwendung übergeben werden. Im folgenden Beispiel sehen Sie eine Anwendung, die mit nur einem Befehlszeilenargument („/StartMinimized“) gestartet wird:

wpfapplication.exe /StartMinimized

Während der Initialisierung der Anwendung ruft WPF die Befehlszeilenargumente aus dem Betriebssystem ab und übergibt sie dem Startup-Ereignishandler über die Args-Eigenschaft des StartupEventArgs-Parameters. Mit Code wie dem folgenden können Sie Befehlszeilenargumente abrufen und speichern.

<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

Der Code verarbeitet Startup, um zu überprüfen, ob das Befehlszeilenargument /StartMinimized angegeben wurde; wenn das der Fall ist, öffnet er das Hauptfenster mit dem WindowStateMinimized. Beachten Sie, dass aufgrund der Tatsache, dass die WindowState-Eigenschaft programmgesteuert festgelegt werden muss, das Haupt-Window explizit im Code geöffnet werden muss.

XBAPs können keine Befehlszeilenargumente abrufen und verarbeiten, da sie mithilfe von ClickOnce-Bereitstellung gestartet werden (siehe Bereitstellen von WPF-Anwendungen). Von den zum Starten verwendeten URLs können jedoch Abfragezeichenfolgenparameter abgerufen und verarbeitet werden.

Aktivieren und Deaktivieren von Anwendungen

Windows ermöglicht es Benutzern, zwischen Anwendungen zu wechseln. Meistens wird dazu die Tastenkombination ALT+TAB verwendet. Es kann nur dann zu einer Anwendung gewechselt werden, wenn sie über ein sichtbares Window verfügt, das ein Benutzer auswählen kann. Das derzeit ausgewählte Window ist das aktive Fenster (oder Vordergrundfenster) und das Window, das Benutzereingaben empfängt. Die Anwendung mit dem aktiven Fenster ist die aktive Anwendung (oder Vordergrundanwendung). Eine Anwendung wird unter folgenden Umständen zur aktiven Anwendung:

  • Sie wird gestartet und zeigt ein Window an.

  • Ein Benutzer wechselt von einer anderen Anwendung, indem er in der Anwendung ein Window auswählt.

Sie können erkennen, wenn eine Anwendung aktiv wird, indem Sie das Application.Activated-Ereignis verarbeiten.

Auf ähnliche Weise kann eine Anwendung unter folgenden Umständen inaktiv werden:

  • Ein Benutzer wechselt von der aktuellen zu einer anderen Anwendung.

  • Wenn die Anwendung heruntergefahren wird.

Sie können erkennen, wenn eine Anwendung inaktiv wird, indem Sie das Application.Deactivated-Ereignis verarbeiten.

Der folgende Code zeigt die Behandlung der Ereignisse Activated und Deactivated, um zu bestimmen, ob eine Anwendung aktiv ist.

<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

Ein Window kann ebenfalls aktiviert und deaktiviert werden. Weitere Informationen finden Sie unter Window.Activated und Window.Deactivated.

Hinweis

Für XBAPs wird weder Application.Activated noch Application.Deactivated ausgelöst.

Herunterfahren einer Anwendung

Die Lebensdauer einer Anwendung endet mit dem Herunterfahren, das aus folgenden Gründen erfolgen kann:

  • Ein Benutzer schließt jedes Window.

  • Ein Benutzer schließt das Haupt-Window.

  • Ein Benutzer beendet die Windows-Sitzung, indem er sich abmeldet oder das Betriebssystem herunterfährt.

  • Eine anwendungsspezifische Bedingung wurde erfüllt.

Um Sie beim Verwalten des Herunterfahrens der Anwendung zu unterstützen, stellt Application die Methode Shutdown, die Eigenschaft ShutdownMode und die Ereignisse SessionEnding und Exit zur Verfügung.

Hinweis

Shutdown kann nur von Anwendungen aufgerufen werden, die über UIPermission verfügen. Eigenständige WPF-Anwendungen verfügen immer über diese Berechtigung. Dies ist bei XBAPs, die im teilweise vertrauenswürdigen Sicherheitsbereich (Sandbox) der Internetzone ausgeführt werden, nicht der Fall.

Modus für das Herunterfahren

Anwendungen werden in der Regel entweder heruntergefahren, wenn alle Fenster geschlossen werden, oder wenn das Hauptfenster geschlossen wird. Manchmal kann jedoch auch durch andere anwendungsspezifische Bedingungen bestimmt werden, wann eine Anwendung heruntergefahren wird. Sie können die Bedingungen angeben, unter denen Ihre Anwendung heruntergefahren wird, indem Sie ShutdownMode auf einen der folgenden ShutdownMode-Enumerationswerte festlegen:

Der Standardwert von ShutdownMode ist OnLastWindowClose, was bedeutet, dass eine Anwendung automatisch heruntergefahren wird, sobald das letzte Fenster der Anwendung vom Benutzer geschlossen wird. Ihre Anwendung sollte jedoch heruntergefahren werden, wenn das Hauptfenster geschlossen wird, WPF erledigt das automatisch, wenn Sie ShutdownMode auf OnMainWindowClose festlegen. Dies wird im folgenden Beispiel gezeigt.

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

Bei anwendungsspezifischen Bedingungen für das Herunterfahren legen Sie ShutdownMode auf OnExplicitShutdown fest. In diesem Fall müssen Sie sicherstellen, dass Sie eine Anwendung herunterfahren, indem Sie explizit die Shutdown-Methode aufrufen. Andernfalls wird die Anwendung weiterhin ausgeführt, auch wenn alle Fenster geschlossen sind. Beachten Sie, dass Shutdown implizit aufgerufen wird, wenn der ShutdownMode entweder OnLastWindowClose oder OnMainWindowClose ist.

Hinweis

ShutdownMode kann von einer XBAP aus festgelegt werden, dies wird jedoch ignoriert. Eine XBAP wird immer heruntergefahren, wenn man in einem Browser von ihr weg navigiert oder wenn der Browser, der die XBAP hostet, geschlossen wird. Weitere Informationen finden Sie unter Übersicht über die Navigation.

Beenden einer Sitzung

Die durch die ShutdownMode-Eigenschaft beschriebenen Bedingungen zum Herunterfahren sind für eine Anwendung spezifisch. In einigen Fällen kann eine Anwendung aber auch als Ergebnis einer externen Bedingung heruntergefahren werden. Die gängigste externe Bedingung tritt auf, wenn ein Benutzer die Windows-Sitzung durch die folgenden Aktionen beendet:

  • Abmelden

  • Herunterfahren

  • Neustarten

  • Wechseln in den Ruhezustand

Um zu erkennen, wann eine Windows-Sitzung endet, können Sie das SessionEnding-Ereignis behandeln, wie im folgenden Beispiel dargestellt.

<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 diesem Beispiel untersucht der Code die ReasonSessionEnding-Eigenschaft, um zu bestimmen, wie die Windows-Sitzung beendet wird. Dieser Wert wird verwendet, um dem Benutzer eine Bestätigungsmeldung anzuzeigen. Wenn der Benutzer nicht möchte, dass die Sitzung endet, legt der Code Cancel auf true fest, um das Beenden der Windows-Sitzung zu verhindern.

Hinweis

SessionEnding wird für XBAPs nicht ausgelöst.

Beenden

Beim Herunterfahren einer Anwendung werden evtl. abschließende Verarbeitungsaufgaben ausgeführt, z. B. Beibehalten des Anwendungszustands. Für diese Situationen können Sie das Exit-Ereignis behandeln, wie es der App_Exit-Ereignishandler im folgenden Beispiel ausführt. Er ist in der App.xaml-Datei als Ereignishandler definiert. Seine Implementierung ist in den Dateien App.xaml.cs und Application.xaml.vb hervorgehoben.

<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

Das vollständige Beispiel finden Sie unter Beibehalten und Wiederherstellen von Eigenschaften für den Anwendungsbereich über mehrere Anwendungssitzungen.

Exit kann sowohl von eigenständigen Anwendungen als auch von XBAPs verarbeitet werden. Für XBAPs wird Exit unter den folgenden Bedingungen ausgelöst:

  • Es wird von einer XBAP weg navigiert.

  • In Internet Explorer wird die Registerkarte geschlossen, auf der die XBAP gehostet wird.

  • Wenn der Browser geschlossen wird.

Exitcode

Anwendungen werden meistens durch das Betriebssystem als Reaktion auf eine Benutzeranforderung gestartet. Eine Anwendung kann aber auch von einer anderen Anwendung gestartet werden, um eine bestimmte Aufgabe zu übernehmen. Wenn die gestartete Anwendung heruntergefahren wird, muss die startende Anwendung möglicherweise über die Bedingung informiert werden, unter der die gestartete Anwendung heruntergefahren wurde. In diesen Situationen ermöglicht Windows es Anwendungen, beim Herunterfahren einen Anwendungsexitcode zurückzugeben. Standardmäßig geben WPF-Anwendungen den Exitcodewert 0 (null) zurück.

Hinweis

Wenn Sie aus Visual Studio debuggen, wird der Anwendungsexitcode beim Herunterfahren im Ausgabefenster angezeigt. Die entsprechende Meldung sieht ungefähr folgendermaßen aus:

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

Sie öffnen das Ausgabefenster, indem Sie im Menü Ansicht auf Ausgabe klicken.

Zum Ändern des Exitcodes können Sie die Shutdown(Int32)-Überladung aufrufen, die ein Ganzzahlargument als Exitcode akzeptiert:

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

Sie können den Wert des Exitcodes ermitteln und ändern, indem Sie das Exit-Ereignis behandeln. Dem Exit-Ereignishandler wird ein ExitEventArgs übergeben, das Zugriff auf den Exitcode mit der ApplicationExitCode-Eigenschaft bietet. Weitere Informationen finden Sie unter Exit.

Hinweis

Sie können den Exitcode sowohl in eigenständigen Anwendungen als auch in XBAPs festlegen. Der Exitcodewert wird für XBAPs allerdings ignoriert.

Nicht behandelte Ausnahmen

Es kommt vor, dass eine Anwendung unter nicht ordnungsgemäßen Bedingungen heruntergefahren wird, z. B. wenn eine unerwartete Ausnahme ausgelöst wird. In diesem Fall verfügt die Anwendung möglicherweise nicht über den Code, der zum Erkennen und Verarbeiten der Ausnahme erforderlich ist. Eine solche Ausnahme wird als nicht behandelte Ausnahme bezeichnet. Vor dem Schließen der Anwendung wird eine Meldung angezeigt, die der folgenden ähnelt.

Screenshot that shows an unhandled exception notification.

Für die Benutzererfahrung ist es vorteilhafter, wenn eine Anwendung dieses Standardverhalten vermeidet. Dazu dienen mehrere oder alle der folgenden Aktionen:

  • Anzeigen von benutzerfreundlichen Informationen

  • Versuchen, eine Anwendung weiterhin auszuführen

  • Aufzeichnen ausführlicher, entwicklerfreundlicher Ausnahmeinformationen im Windows-Ereignisprotokoll

Die Implementierung dieser Unterstützung hängt von der Fähigkeit ab, nicht behandelte Ausnahmen zu erkennen, was der Grund für das Auslösen des DispatcherUnhandledException-Ereignisses ist.

<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

Dem DispatcherUnhandledException-Ereignishandler wird ein DispatcherUnhandledExceptionEventArgs-Parameter übergeben, der Kontextinformationen zur nicht behandelten Ausnahme enthält, einschließlich der Ausnahme selbst (DispatcherUnhandledExceptionEventArgs.Exception). Sie können anhand dieser Informationen feststellen, wie die Ausnahme behandelt werden soll.

Wenn Sie DispatcherUnhandledException behandeln, sollten Sie die DispatcherUnhandledExceptionEventArgs.Handled-Eigenschaft auf true festlegen. Andernfalls sieht WPF die Ausnahme nach wie vor als unbehandelt an und kehrt zum zuvor beschriebenen Standardverhalten zurück. Wenn ein Ausnahmefehler ausgelöst wird und entweder das DispatcherUnhandledException-Ereignis nicht behandelt wurde, oder das Ereignis wurde behandelt, und Handled wurde auf false festgelegt, wird die Anwendung sofort heruntergefahren. Darüber hinaus werden keine weiteren Application-Ereignisse ausgelöst. Folglich müssen Sie DispatcherUnhandledException behandeln, wenn die Anwendung über Code verfügt, der vor dem Herunterfahren ausgeführt werden muss.

Obwohl eine Anwendung wegen einer nicht behandelten Ausnahme heruntergefahren werden kann, erfolgt das Herunterfahren normalerweise als Reaktion auf eine Benutzeranforderung, wie im nächsten Abschnitt beschrieben.

Anwendungslebensdauer-Ereignisse

Eigenständige Anwendungen und XBAPs haben nicht genau dieselbe Lebensdauer. Die folgende Abbildung veranschaulicht die wichtigsten Ereignisse in der Lebensdauer einer eigenständigen Anwendung und die Reihenfolge, in der sie ausgelöst werden.

Standalone Application - Application Object Events

Entsprechend veranschaulicht die folgende Abbildung die wichtigsten Ereignisse in der Lebensdauer einer XBAP und zeigt, in welcher Reihenfolge diese ausgelöst werden.

XBAP - Application Object Events

Siehe auch