共用方式為


應用程式管理概觀

所有應用程式通常會共用一組適用於應用程式實作和管理的通用功能。 本文提供 Application 類別中用來建立和管理應用程式的功能概觀。

應用程式類別

在 WPF 中,常見的應用程式範圍功能會封裝在 Application 類別中。 Application 類別包含下列功能:

  • 追蹤應用程式存留期並與其互動。

  • 擷取及處理命令列參數。

  • 偵測及回應未處理的例外狀況。

  • 共用應用程式範圍的屬性和 資源。

  • 管理獨立應用程式中的視窗。

  • 追蹤及管理瀏覽。

如何使用 Application 類別執行一般工作

如果您對 Application 類別的完整細節不感興趣,下表列出 Application 的一些常見工作以及完成方式。 您可以檢視相關的 API 和主題,來尋找詳細資訊和範例程式碼。

Task 方法
取得代表目前應用程式的物件 請使用 Application.Current 屬性。
將啟動畫面新增至應用程式 請參閱將啟動顯示畫面新增至 WPF 應用程式
啟動應用程式 使用 Application.Run 方法。
停止應用程式 使用 Application.Current 物件的 Shutdown 方法。
從命令列取得引數 處理 Application.Startup 事件,並使用 StartupEventArgs.Args 屬性。 如需範例,請參閱 Application.Startup 事件。
取得及設定應用程式結束代碼 Application.Exit 事件處理常式中設定 ExitEventArgs.ApplicationExitCode 屬性,或呼叫 Shutdown 方法並傳入整數。
偵測及回應未處理的例外狀況 處理 DispatcherUnhandledException 事件。
取得及設定應用程式範圍的資源 請使用 Application.Current 屬性。
使用應用程式範圍的資源字典 請參閱使用應用程式範圍的資源字典
取得及設定應用程式範圍的屬性 請使用 Application.Current 屬性。
取得及儲存應用程式的狀態 請參閱跨應用程式工作階段保存和還原應用程式範圍的屬性
管理非程式碼資料檔案,包括資源檔、內容檔案和來源網站檔案。 請參閱 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 建立衍生自 Applicationpartial 類別,並具有由 x:Class 屬性所指定的名稱。 這需要新增 XAML 結構描述的 XML 命名空間宣告 (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml")。

  • 在程式碼後置中,此類別必須是具有標記中 x:Class 屬性所指定之相同名稱的 partial 類別,而且必須衍生自 Application。 這可讓程式碼後置檔案與建置應用程式時為標記檔案產生的 partial 類別相關聯 (請參閱建置 WPF 應用程式)。

注意

當您使用 Visual Studio 建立新的 WPF 應用程式專案或 WPF 瀏覽器應用程式專案時,預設會包含應用程式定義,並使用標記和程式碼後置來定義。

此程式碼是實作應用程式定義的最低需求。 不過,在建置及執行應用程式之前,您必須對應用程式定義進行一項額外的 MSBuild 組態。

設定 MSBuild 的應用程式定義

獨立應用程式和 XAML 瀏覽器應用程式 (XBAP) 需要加入一定程度的基礎結構才能執行。 此基礎結構的最重要部分是進入點。 當使用者啟動應用程式時,作業系統會呼叫進入點,這是用於啟動應用程式的已知函式。

警告

XBAP 需要舊版瀏覽器才能運作,例如 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>

由於程式碼後置檔案包含程式碼,因此在正常情況下會標記為 MSBuild Compile 項目。

將這些 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

產生的程式碼會透過額外的基礎結構程式碼來增強您的應用程式,其中包含進入點方法 MainSTAThreadAttribute 屬性會套用至 Main 方法,指出 WPF 應用程式的主要 UI 執行緒是 WPF 應用程式所需的 STA 執行緒。 呼叫時,Main 會建立 App 的新執行個體,再呼叫 InitializeComponent 方法,以註冊事件,並設定要在標記中加入的屬性。 由於系統會為您產生 InitializeComponent,因此您不需要像針對 PageWindow 實作一樣,從應用程式定義明確呼叫 InitializeComponent。 最後,系統會呼叫 Run 方法來啟動應用程式。

取得目前的應用程式

由於 Application 類別的功能會跨應用程式共用,因此每個 AppDomain 只能有一個 Application 類別的執行個體。 為強制執行這項作業,Application 類別會以單一類別實行 (請參閱在 C# 中實作 Singleton),這會建立本身的單一執行個體,並提供與 staticCurrent 屬性共用的存取權。

下列程式碼示範如何取得目前 AppDomainApplication 物件的參考。

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

您可以在 Application 物件存留期間中的任何時間點檢查 Current 的值。 不過,您應該要小心。 生成 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>

在應用程式存留期中的這個時間點,最常執行的工作是顯示 UI。

顯示使用者介面

大多數獨立 Windows 應用程式會在開始執行時開啟 WindowStartup 事件處理常式是可以執行此作業的其中一個位置,如下列程式碼所示範。

<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 預設會成為主應用程式視窗。 Application.MainWindow 屬性參考 Window 物件。 如果主視窗應該是第一個具現化之 Window 以外的其他視窗,可以透過程式設計的方式變更 MainWindow 屬性的值。

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

下列範例示範如何使用 XBAP 中的 StartupUri 來移動至 Page

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

此標記與前述用來開啟視窗的程式碼有相同的效果。

注意

如需瀏覽的詳細資訊,請參閱瀏覽概觀

在下列情況下,您必須處理 Startup 事件來開啟 Window:開始需要使用非預設建構函式進行生成、需要在顯示它之前設定其屬性或訂閱其事件,或是需要處理啟動應用程式時所提供的任何命令列引數。

處理命令列引數

在 Windows 中,您可以從命令提示字元或桌面啟動獨立應用程式。 在這兩種情況下,都會將命令列引數傳遞至應用程式。 下列範例顯示以單一命令列引數 "/StartMinimized" 啟動的應用程式:

wpfapplication.exe /StartMinimized

在應用程式初始化期間,WPF 會從作業系統擷取命令列引述,並透過 StartupEventArgs 參數的 Args 屬性,將它們傳遞至 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)
        {
            // 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 命令列引數是否已提供;若是如此,則會以 MinimizedWindowState開啟主視窗。 請注意,由於 WindowState 屬性必須以程式方式設定,因此必須在程式碼中明確開啟主要 Window

XBAP 無法擷取及處理命令列引數,因為它們是使用 ClickOnce 部署來啟動 (請參閱部署 WPF 應用程式)。 不過,它們可以透過用來啟動的 URL 擷取及處理查詢字串參數。

應用程式啟用和停用

Windows 可讓使用者在應用程式之間切換。 最常見的做法是使用 ALT+TAB 按鍵組合。 只有在應用程式具有使用者可以選取的可見 Window 時,使用者才能切換到該應用程式。 目前選取的 Window使用中視窗 (又稱為前景視窗),也是接收使用者輸入的 Window。 具有使用中視窗的應用程式是「使用中應用程式」 (或「前景應用程式」)。 在下列情況中,應用程式會變成使用中應用程式:

  • 它會啟動並顯示 Window

  • 使用者藉由在應用程式中選取 Window,來從另一個應用程式進行切換。

您可以藉由處理 Application.Activated 事件來偵測應用程式何時變成使用中狀態。

同樣地,在下列情況中,應用程式會變成非使用中:

  • 使用者從目前的應用程式切換至另一個應用程式。

  • 應用程式關閉時。

您可以藉由處理 Application.Deactivated 事件來偵測應用程式何時變成非使用中狀態。

下列程式碼示範如何處理 ActivatedDeactivated 事件,以判斷應用程式是否使用中。

<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.ActivatedWindow.Deactivated

注意

XBAP 不會引發 Application.ActivatedApplication.Deactivated

應用程式關閉

應用程式一旦關閉,其存留期間便告結束,而應用程式關閉的可能原因包括:

  • 使用者關閉每個 Window

  • 使用者關閉主要 Window

  • 使用者透過登出或關機結束 Windows 工作階段。

  • 已符合應用程式特定條件。

為了協助您關閉應用程式,Application 提供 Shutdown 方法、ShutdownMode 屬性,以及 SessionEndingExit 事件。

注意

Shutdown 只能從具有 UIPermission 的應用程式呼叫。 獨立 WPF 應用程式一律會有此權限。 不過,在網際網路區域部分信任安全性沙箱中執行的 XBAP 則沒有此權限。

程式關閉模式

大多數應用程式會在所有視窗關閉或主視窗關閉時一併關閉。 不過有時候,應用程式關閉的時機可能是由其他應用程式特定條件決定。 您可以使用下列其中一個 ShutdownMode 列舉值來設定 ShutdownMode ,以指定應用程式關閉的條件:

ShutdownMode 的預設值是 OnLastWindowClose,表示應用程式會在使用者關閉應用程式的最後一個視窗時自動關閉。 不過,如果您的應用程式應該在主視窗關閉時關閉,您只需將 ShutdownMode 設定為 OnMainWindowClose,WPF 便會自動關閉主視窗。 下列範例會顯示這一點。

<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 方法來關閉應用程式;否則,即使所有視窗都已關閉,應用程式仍會繼續執行。 請注意,當 ShutdownModeOnLastWindowCloseOnMainWindowClose 時,會隱含呼叫 Shutdown

注意

您可以從 XBAP 設定 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 工作階段的結束方式。 接著,它會使用這個值對使用者顯示確認訊息。 如果使用者不希望工作階段結束,程式碼會將 Cancel 設定為 true 以防止 Windows 工作階段結束。

注意

XBAP 不會引發 SessionEnding

結束

當應用程式關閉時,可能需要執行一些最終處理作業,例如保存應用程式狀態。 在這些情況下,您可以處理 Exit 事件,如下列範例中的 App_Exit 事件處理常式的處理方式。 其在 App.xaml 檔案中定義為事件處理常式。 其實作會在 App.xaml.csApplication.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

如需完整範例,請參閱跨應用程式工作階段保存和還原應用程式範圍的屬性

獨立應用程式和 XBAP 都可以處理 Exit。 就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獨立應用程式 - 應用程式物件事件ApplicationModelOverview_ApplicationObjectEvents

同樣地,下圖說明 XBAP 存留期內的主要事件,並顯示這些事件的引發順序。

XBAP - Application Object EventsXBAP - 應用程式物件事件ApplicationModelOverview_ApplicationObjectEvents_xbap

另請參閱