Поделиться через


Обзор управления приложениями

Все приложения, как правило, используют общий набор функциональных возможностей, которые применяются к реализации и управлению приложениями. В этом разделе представлен обзор функциональных возможностей в классе 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-Scope.
Получение и установка свойств, охватывающих область приложения Используйте свойство Application.Properties.
Получение и сохранение состояния приложения См. свойства Сохранение и Восстановление Application-Scope для сеансов приложений.
Управление файлами данных, отличными от кода, включая файлы ресурсов, файлы содержимого и файлы источника. См. ресурс приложения WPF, содержимое и файлы данных .
Управление окнами в автономных приложениях См. в обзоре WPF для Windows.
Учёт и управление навигацией См. обзор навигации.

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

Чтобы использовать функциональные возможности класса 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. Для этого требуется добавление объявления пространства имен XML для схемы XAML (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml").

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

Заметка

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

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

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

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

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

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

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

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

Поскольку файл code-behind содержит код, он помечается как элемент MSBuild Compile, как это является нормой.

Применение этих конфигураций 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 совместно используются в приложении, для каждого AppDomainможет быть только один экземпляр класса Application. Для этого класс Application реализуется как класс синглтон (см. раздел Реализация Singleton в 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 с пакетом обновления 1 (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, если необходимо создать экземпляр его с помощью конструктора без параметров или задать его свойства или подписаться на его события, прежде чем отображать его, или необходимо обработать все аргументы командной строки, предоставленные при запуске приложения.

Обработка аргументов Command-Line

В 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; если да, то открывается основное окно с WindowStateMinimized. Обратите внимание, что поскольку свойство WindowState должно быть задано программным способом, основной Window должен быть открыт явным образом в коде.

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

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

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

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

Окончание сеанса

Условия завершения работы, описанные свойством 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. Это значение используется для отображения сообщения подтверждения пользователю. Если пользователь не хочет, чтобы сеанс закончился, код задает Canceltrue, чтобы предотвратить завершение сеанса Windows.

Заметка

SessionEnding не вызывается для XBAPs.

Выход

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

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

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

  • От XBAP осуществляется переход.

  • Когда закрывается вкладка, хранящая XBAP, в Internet Explorer.

  • При закрытии браузера.

Код выхода

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

Заметка

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

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

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

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

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

  • Отображение понятных сведений.

  • Попытка сохранить работу приложения.

  • Запись подробных сведений об исключениях, понятных для разработчиков, в журнале событий 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, если у приложения есть код, который должен выполняться до завершения работы приложения.

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

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

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

автономное приложение — события объектов приложения

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

XBAP — события объектов приложения

См. также