Общие сведения об управлении приложением

Все приложения имеют тенденцию совместно использовать общий набор функциональных возможностей, который применяется к реализации приложения и управлению им. В этом разделе приводится обзор функциональных возможностей, предоставляемых в классе Application для создания приложений и управления ими.

Класс приложений

В WPF общие функциональные возможности области определения приложения инкапсулируются в классе Application. Класс Application предоставляет следующие возможности:

  • отслеживание и взаимодействие со временем существования приложения;

  • извлечение и обработка параметров командной строки;

  • обнаружение необработанных исключений и реагирование на них;

  • совместное использование свойств области приложения и ресурсов ;

  • управление окнами в автономных приложениях;

  • отслеживание навигации и управление ею.

Выполнение стандартных задач с помощью класса приложения

Если требуются не все возможности класса Application, обратитесь к приведенной ниже таблице, в которой перечислены некоторые из наиболее распространенных задач класса Application с указанием способа их выполнения. Чтобы получить дополнительные сведения и образец кода, просмотрите связанные API и разделы.

Задача Подход
Получение объекта, представляющего текущее приложение Используйте свойство Application.Current.
Добавление заставки в приложение См. раздел Добавление в WPF-приложение экрана-заставки.
Запуск приложения Используйте метод Application.Run.
Остановка приложения Используйте метод Shutdown объекта Application.Current.
Получение аргументов из командной строки Обработайте событие Application.Startup и используйте свойство StartupEventArgs.Args. В качестве примера см. событие Application.Startup.
Получение и задание кода завершения приложения Задайте свойство ExitEventArgs.ApplicationExitCode в обработчике события Application.Exit или вызовите метод Shutdown, передав в него целое число.
Обнаружение необработанных исключений и реагирование на них Обработайте событие DispatcherUnhandledException.
Получение и задание ресурсов области определения приложения Используйте свойство Application.Resources.
Использование словаря ресурсов области определения приложения См. раздел Использование словаря ресурсов области определения приложения.
Получение и задание свойств области определения приложения Используйте свойство Application.Properties.
Получение и сохранение состояния приложения См. раздел Сохранение и восстановление свойств области определения приложения в сеансах приложения.
Управление файлами данных без кода, включая файлы ресурсов, файлы содержимого и файлы исходного сайта. См. раздел Файлы ресурсов, содержимого и данных WPF-приложения.
Управление окнами в автономных приложениях См. раздел Общие сведения об окнах WPF.
Отслеживание навигации и управление ею См. раздел Общие сведения о переходах.

Определение приложения

Чтобы использовать возможности класса Application, необходимо реализовать определение приложения. Определение приложения WPF представляет собой класс, производный от Application и настроенный со специальным параметром MSBuild.

Реализация определения приложения

Типичное определение приложения WPF реализуется с помощью разметки и кода программной части. Это позволяет использовать разметку для декларативного задания свойств и ресурсов приложения и регистрации событий, а обработку событий и поведение приложения реализовывать в коде программной части.

В следующем примере показано, как реализовать определение приложения с помощью разметки и кода программной части:

<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

Для совместной работы файла разметки и файла кода программной части должны выполняться указанные ниже условия.

  • В разметке элемент Application должен включать атрибут x:Class. При построении приложения существование x:Class в файле разметки вызывает MSBuild для создания класса partial, который является производным от Application и имеет имя, указанное в атрибуте x:Class. Для этого требуется добавить объявление пространства имен XAML в схему XAML (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml").

  • В коде программной части класс должен быть классом partial с тем же именем, которое определено атрибутом x:Class в разметке. Кроме того, этот класс должен быть производным от Application. Это позволяет связать файл кода программной части с классом partial, созданным для файла разметки при построении приложения (см. раздел Построение приложения WPF).

Примечание.

При создании проекта приложения WPF или проекта приложения браузера WPF с помощью Visual Studio определение приложения добавляется по умолчанию и определяется с помощью разметки и кода программной части.

Этот код является минимумом, необходимым для реализации определения приложения. Но перед сборкой и запуском приложения должна быть создана дополнительная конфигурация MSBuild для определения приложения.

Настройка определения приложения для MSBuild

Автономные приложения и XAML-приложения браузера (XBAP) требуют реализации инфраструктуры определенного уровня перед своим запуском. Наиболее важной частью этой инфраструктуры является точка входа. При запуске приложения пользователем операционная система вызывает точку входа, которая является известной функцией для запуска приложений.

Предупреждение

Для работы XBAPs требуются устаревшие браузеры, такие как интернет-Обозреватель и Firefox. Эти старые версии браузера обычно не поддерживаются в Windows 10 и Windows 11. Современные браузеры больше не поддерживают технологию, необходимую для приложений XBAP из-за рисков безопасности. Подключаемые модули, поддерживающие XBAP, больше не поддерживаются.

Обычно разработчикам требовалось писать весь этот код или его часть самостоятельно в зависимости от технологии. Но WPF создает этот код автоматически при настройке файла разметки для определения приложения в качестве элемента ApplicationDefinition в MSBuild, как показано в следующем файле проекта MSBuild:

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

Так как файл кода программной части содержит код, он помечается как элемент Compile в MSBuild, что является нормальным.

Применение этих конфигураций MSBuild к файлам разметки и кода программной части для определения приложения приводит к тому, что MSBuild создает код, подобный следующему:

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

Результирующий код дополняет ваше определение приложения кодом инфраструктуры, содержащим метод точки входа Main. Атрибут STAThreadAttribute применяется к методу Main, указывая, что основной поток пользовательского интерфейса для приложения WPF является потоком STA, обязательным для приложений WPF. При вызове метод Main создает экземпляр класса App перед вызовом метода InitializeComponent с целью регистрации событий и установки свойств, реализованных в разметке. Так как InitializeComponent создается автоматически, не требуется явно вызывать InitializeComponent из определения приложения, как для реализаций Page и Window. Наконец, вызывается метод Run для запуска приложения.

Получение текущего приложения

Так как возможности класса Application совместно используются во всем приложении, может быть только один экземпляр класса Application в каждом AppDomain. Для выполнения этого требования класс Application реализуется как допускающий создание только одного экземпляра (см. раздел Реализация класса, допускающего создание только одного экземпляра, в C#). Он создает один экземпляр себя и обеспечивает общий доступ к нему с помощью свойства staticCurrent.

В следующем коде показывается, как получать ссылку на объект Application для текущего AppDomain.

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

Current возвращает ссылку на экземпляр классаApplication. Если вам нужна ссылка на ваш производный класс Application, необходимо выполнить приведение значения свойства Current, как показано в следующем примере.

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

Проверить значение Current можно в любой момент в течение времени существования объекта Application. Однако следует соблюдать осторожность. После создания экземпляра класса Application есть период времени, в течение которого состояния объекта Application не согласовано. В течение этого периода Application выполняет различные задачи инициализации, необходимые для выполнения кода, включая установку инфраструктуры приложения, настройку свойств и регистрацию событий. Если попытаться использовать объект Application в течение этого периода, то выполнение кода может привести к неожиданным результатам, особенно если код зависит от различных устанавливаемых свойств Application.

Фактически, время существования объекта Application начинается после завершения действий по его инициализации.

Время существования приложения

Время существования приложения WPF отмечается несколькими событиями, которые вызываются объектом Application, чтобы сообщить, когда приложение запускается, активируется, отключается и завершает работу.

Экран-заставка

Начиная с версии .NET Framework 3.5 SP1, можно указать изображение, которое должно использоваться в заставке или на экране-заставке. Класс SplashScreen позволяет легко отобразить заставку во время загрузки приложения. Создается окно SplashScreen, которое показывается перед выводом Run. Дополнительные сведения см. в разделах Время запуска приложения и Добавление в WPF-приложение экрана-заставки.

Запуск приложения

После вызова Run и инициализации приложения приложение готово к запуску. Признаком этого момента является возникающее событие 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>

В этот момент времени существования приложения наиболее обычным действием является вывод на экран пользовательского интерфейс.

Отображение пользовательского интерфейса

Большинство автономных приложений Windows, начиная выполнение, открывают Window. Для этого можно использовать, например, обработчик событий Startup, как показано в приведенном ниже коде.

<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

Примечание.

Первый экземплярWindow, создаваемый в автономном приложении, по умолчанию становится главным окном приложения. Этот объект Window возвращается свойством Application.MainWindow. Значение свойства MainWindow может быть изменено программными средствами, если главным должно быть другое окно, а не первый экземпляр Window.

При первом запуске XBAP-приложения, оно скорее всего перейдет к объекту Page. Это показано в приведенном ниже коде.

<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

При обработке Startup, чтобы только открыть окно Window или перейти к странице Page, можно вместо этого задать в разметке атрибут StartupUri.

В следующем примере показывается, как использовать StartupUri из автономного приложения, чтобы открыть Window.

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

В следующем примере показано, как использовать StartupUri XBAP-приложения для перехода к объекту Page.

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

Эта разметка действует так же, как и предыдущий код для открытия окна.

Примечание.

Дополнительные сведения о переходах см. в разделе Общие сведения о переходах.

Необходимо обрабатывать событие Startup, чтобы открыть объект Window, если нужно создать его экземпляр с помощью конструктора не по умолчанию, задать его свойства либо подписаться на его события перед его отображением или обработать любые аргументы командной строки, заданные при запуске приложения.

Обработка аргументов командной строки

В Windows автономные приложения можно запускать из командной строки или с рабочего стола. В обоих случаях аргументы командной строки могут быть переданы приложению. В приведенном ниже примере показано приложение, которое запускается с одним аргументом командной строки /StartMinimized:

wpfapplication.exe /StartMinimized

При инициализации приложения WPF получает аргументы командной строки из операционной системы и передает из в обработчик событий Startup, используя свойство Args параметра StartupEventArgs. Аргументы командной строки можно извлечь и сохранить с помощью приведенного ниже кода.

<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

Код обрабатывает Startup, чтобы проверить, предоставлен ли аргумент командной строки /StartMinimized. Если он бы предоставлен, главное окно открывается с состоянием WindowState, равным Minimized. Обратите внимание, что, так как свойство WindowState должно устанавливаться программным образом, главное окно Window должно явно открываться в коде.

Приложения XBAP не могут получать и обрабатывать аргументы командной строки, так как они запускаются с помощью развертывания ClickOnce (см. раздел Развертывание приложений WPF). Однако они могут извлекать и обрабатывать строковые параметры запроса из URL-адресов, которые используются для их запуска.

Активация и отключение приложения

Windows позволяет пользователям переключаться между приложениями. Наиболее простой способ — использовать клавиши ALT+TAB. В приложение можно переключиться, только если оно содержит видимое окно Window, которое может выбрать пользователь. Выбранный в данный момент объект Window является активным окном (также известным как окно переднего плана), и именно это окно Window получает фокус ввода данных пользователя. Приложение с активным окном является активным приложением (или приложением переднего плана). Приложение становится активным в указанных ниже случаях.

  • Оно запускается и отображает окно Window.

  • Пользователь переключается из другого приложения, выбирая окно Window в приложении.

Обнаружить, что приложение стало активным, можно, обрабатывая событие Application.Activated.

Аналогичным образом приложение может стать неактивным в указанных ниже случаях.

  • Пользователь переключается на другое приложение из текущего.

  • Приложение завершает работу.

Обнаружить, что приложение становится неактивным, можно, обрабатывая событие Application.Deactivated.

В следующем коде показывается, как обрабатывать события Activated и Deactivated, чтобы определить, активно ли приложение.

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

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

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

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

Imports System.Windows

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

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

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

Окно Window также можно сделать активным или неактивным. Дополнительные сведения см. в разделах Window.Activated и Window.Deactivated.

Примечание.

Ни Application.Activated, ни Application.Deactivated для приложения XBAP не возникают.

Завершение работы приложения

Время существования приложения заканчивается, когда оно завершает работу, что может возникнуть по указанным ниже причинам.

  • Пользователь закрывает все окна Window.

  • Пользователь закрывает главное окно Window.

  • Пользователь завершает сеанс Windows, выходя из системы или завершая работу системы.

  • Выполнено специальное условие для приложения.

Для управления завершением работы приложения Application предоставляет метод Shutdown, свойство ShutdownMode, а также события SessionEnding и Exit.

Примечание.

Метод Shutdown может быть вызван только из приложений, обладающих разрешением UIPermission. У автономных приложений WPF всегда есть это разрешение. Но приложения XBAP, выполняющиеся в изолированной среде безопасности зоны Интернета с частичным доверием, таким разрешением не обладают.

Режим завершения работы

Большинство приложений завершают работу при закрытии главного окна или всех окон. Иногда, однако, другие условия конкретного приложения могут определить, когда приложение завершает работу. Можно определить условия, при которых приложение будет завершать работу, устанавливая для ShutdownMode одно из следующих значений перечисления ShutdownMode:

По умолчанию значение ShutdownMode равно OnLastWindowClose, в этом случае приложение автоматически завершает работу при закрытии пользователем последнего окна в приложении. Но если приложение должно завершать работу при закрытии главного окна, WPF автоматически делает это, если значение ShutdownMode установлено равным OnMainWindowClose. Это показано в следующем примере.

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

Когда возникают условия завершения работы, специфические для приложения, значение ShutdownMode нужно установить равным OnExplicitShutdown. В этом случае необходимо обеспечить завершение работы приложения, явно вызвав метод Shutdown. В противном случае приложение продолжит выполнение, даже если все окна будут закрыты. Обратите внимание, что Shutdown неявно вызывается, если ShutdownMode равно OnLastWindowClose или OnMainWindowClose.

Примечание.

Значение ShutdownMode можно задать из приложения XBAP, но оно игнорируется. Приложение XBAP всегда завершает работу при переходе из браузера или при закрытии браузера, в котором размещается приложение XBAP. Дополнительные сведения см. в разделе Общие сведения о переходах.

Завершение сеанса

Условия завершения работы, описываемые свойством ShutdownMode, являются специфическими для приложения. Однако в некоторых случаях приложение может завершить работу в результате выполнения внешнего условия. Чаще всего внешнее условие возникает, когда пользователь завершает сеанс Windows, выполняя следующие действия:

  • выход из системы;

  • завершение работы;

  • перезапуск;

  • спящий режим.

Чтобы обнаружить завершение сеанса Windows, можно обработать событие SessionEnding, как показано в приведенном ниже примере.

<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

В этом примере код проверяет свойство ReasonSessionEnding, чтобы определить, как завершается сеанс Windows. Он использует это значение, чтобы отобразить сообщение подтверждения для пользователя. Если пользователь не хочет завершать сеанс, код устанавливает для Cancel значение true, чтобы предотвратить завершение сеанса Windows.

Примечание.

Событие SessionEnding не возникает для приложений XBAP.

Exit

При завершении работы приложения может возникнуть необходимость выполнить окончательную обработку, например сохранение состояния приложения. В таких ситуациях можно обработать событие Exit, как делает обработчик событий App_Exit в следующем примере. Он определяется как обработчик событий в файле App.xaml. Его реализация выделена в файлах App.xaml.cs и 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

Полный пример см. в разделе Сохранение и восстановление свойств области определения приложения в сеансах приложения.

Событие Exit может обрабатываться как автономными приложениями, так и приложениями XBAP. Для приложений XBAP Exit возникает в следующих случаях:

  • Выполняется переход из приложения XBAP.

  • В Internet Explorer при закрытии вкладки, в которой размещается приложение XBAP.

  • Закрывается браузер.

Код завершения

Приложения, как правило, запускаются операционной системой в ответ на запрос пользователя. Однако приложение может быть запущено другим приложением для выполнения определенной задачи. При завершении работы запущенного приложения приложению, которое его запустило, может понадобиться выяснить условие, при котором запущенное приложение завершает работу. В этих случаях Windows разрешает приложениям вернуть код выхода приложения при завершении работы. По умолчанию приложения WPF возвращают значение кода выхода 0.

Примечание.

При отладке из Visual Studio код выхода приложения отображается в окне Вывод, когда приложение завершает работу, в сообщении, которое выглядит следующим образом:

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

Чтобы открыть окно Вывод, выберите в пункт Вывод меню Вид.

Чтобы изменить код выхода, можно вызвать перегрузку метода Shutdown(Int32), который теперь принимает целочисленный аргумент для кода выхода:

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

Определить значение кода выхода и изменить его можно, обработав событие Exit. В обработчик событий Exit передается параметр ExitEventArgs, предоставляющий доступ к коду выхода в свойстве ApplicationExitCode. Дополнительные сведения см. в разделе Exit.

Примечание.

Код выхода можно задавать как в автономных приложениях, так и в приложениях XBAP. Но для приложений XBAP значение кода выхода игнорируется.

Необработанные исключения

Иногда приложение может завершить работу из-за неправильного состояния, например когда создается непредвиденное исключение. В этом случае в приложении может не быть кода для обнаружения и обработки исключения. Исключение такого типа является необработанным. Перед закрытием приложения выводится уведомление, похожее на показанное на рисунке ниже.

Screenshot that shows an unhandled exception notification.

С точки зрения работы пользователя такое поведение приложения по умолчанию лучше переопределить, выполнив некоторые или все следующие действия:

  • отображение понятных для пользователя сведений;

  • попытка продолжить выполнение приложения;

  • запись подробных, понятных разработчику сведений об исключении в журнал событий Windows.

Реализация этих действий зависит от возможности обнаружить необработанные исключения, для чего вызывается событие 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

В обработчик событий DispatcherUnhandledException передается параметр DispatcherUnhandledExceptionEventArgs, содержащий контекстную информацию, касающуюся необработанного исключения, включая само исключение (DispatcherUnhandledExceptionEventArgs.Exception). Эту информацию можно использовать для определения способа обработки исключений.

При обработке DispatcherUnhandledException следует установить свойство DispatcherUnhandledExceptionEventArgs.Handled равным true. В противном случае WPF продолжает считать исключение необработанным и возвращается к описанному ранее поведению по умолчанию. Если возникает необработанное исключение и либо событие DispatcherUnhandledException не обрабатывается, либо обрабатывается и Handled устанавливается равным false, приложение завершает работу немедленно. При этом никакие другие события Application не возникают. Следовательно, если приложение содержит код, который должен выполняться перед завершением работы приложения, нужно обрабатывать DispatcherUnhandledException.

Хотя приложение может завершить работу в результате возникновения необработанного исключения, приложение обычно завершает работу в ответ на запрос пользователя, как описано в следующем разделе.

Событий приложения

У автономных приложений и приложений XBAP разное время существования. На приведенном ниже рисунке продемонстрированы ключевые события времени существования автономного приложения и показана последовательность, в которой они создаются.

Standalone Application - Application Object Events

На приведенном ниже рисунке показаны ключевые события времени существования XBAP и последовательность, в которой они создаются.

XBAP - Application Object Events

См. также