應用程式管理概觀
本主題提供用來建立及管理應用程式之 Windows Presentation Foundation (WPF) 服務的概觀。 WPF 應用程式的核心 (Kernel) 是 Application 類別 (Class),此類別可支援各種核心 (Core) 應用程式服務。 本主題將簡介其中最重要的服務。
這個主題包含下列章節。
- Application 類別
- 應用程式定義
- 取得目前的應用程式
- 應用程式存留期
- 其他應用程式服務
- 相關主題
Application 類別
應用程式是由許多應用程式專屬項目所組成,包括user interface (UI)、商務邏輯、資料存取邏輯、控制項和資料。 這些項目通常隨應用程式而異。 不過,所有的應用程式通常都會共用一組有助於實作 (Implementation) 及管理應用程式的通用功能。 在 WPF 中,這組通用的應用程式範圍功能是封裝在 Application 類別中,並提供下列服務:
建立及管理通用應用程式基礎結構。
追蹤應用程式的存留期 (Lifetime) 並與其互動。
擷取和處理命令列參數。
共用應用程式範圍屬性和資源。
偵測及回應未處理的例外狀況 (Exception)。
傳回結束代碼。
管理獨立應用程式中的視窗 (請參閱 WPF 視窗概觀)。
追蹤及管理巡覽 (請參閱巡覽概觀)。
若要在應用程式中使用這些服務,您必須使用 Application 類別實作應用程式定義。
應用程式定義
WPF 應用程式定義是衍生自 Application 而且已經設定特殊 Microsoft build engine (MSBuild) 設定的類別。
實作應用程式定義
一般的 WPF 應用程式定義都是同時使用標記和程式碼後置 (Code-Behind) 來實作。 這種實作方式可以讓您使用標記,以宣告方式設定應用程式屬性、資源和註冊事件,同時在程式碼後置中處理事件並實作應用程式特有的行為。
下列範例示範如何同時使用標記和程式碼後置來實作應用程式定義:
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App" />
Imports Microsoft.VisualBasic
Imports System.Windows ' Application
Namespace SDKSample
Partial Public Class App
Inherits Application
End Class
End Namespace
using System.Windows; // Application
namespace SDKSample
{
public partial class App : Application { }
}
若要讓標記檔案和程式碼後置的檔案一起運作,必須符合下列條件:
標記中的 Application 項目必須包含 x:Class 屬性 (Attribute)。 建置應用程式時,標記檔案中若存在 x:Class 會造成 MSBuild 建立衍生自 Application 且具有 x:Class 屬性指定之名稱的 partial 類別。 這需要加入 XAML 結構描述的 XML 命名空間 (Namespace) 宣告 (xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml")。
程式碼後置中的類別必須是 partial 類別,並具有標記中 x:Class 屬性所指定的相同名稱,且必須衍生自 Application。 允許程式碼後置的檔案與 partial 類別產生關聯,這個類別是在建置應用程式時根據標記產生的 (請參閱建置 WPF 應用程式 (WPF))。
注意事項 |
---|
當您使用 Microsoft Visual Studio 建立新的 WPF 應用程式專案或 WPF 瀏覽器應用程式專案時,預設會包含應用程式定義,並同時使用標記和程式碼後置加以定義。 |
這個程式碼是實作應用程式定義所需的最基本程式碼。 不過,建置 (Build) 及執行應用程式之前,您還必須對應用程式定義進行一項額外的 MSBuild 組態設定。
設定 MSBuild 的應用程式定義
獨立應用程式和 XAML browser applications (XBAPs) 必須實作特定層級的基礎結構之後才能執行。 這個基礎結構最重要的部分是進入點 (Entry Point)。 當使用者啟動應用程式時,作業系統會呼叫進入點,也就是用來啟動應用程式的已知功能。
依照慣例,開發人員必須自行撰寫這個程式碼的某些部分或全部 (依技術而定)。 不過,WPF 會在將應用程式定義的標記檔案設定為 MSBuild ApplicationDefinition 項目時自動產生這個程式碼,如下列 MSBuild 專案檔所示。
<Project
DefaultTargets="Build"
xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
...
<ApplicationDefinition Include="App.xaml" />
<Compile Include="App.xaml.cs" />
...
</Project>
因為程式碼後置的檔案包含程式碼,所以如同一般情況,這個檔案會標記為 MSBuild Compile 項目。
將這些 MSBuild 組態套用至應用程式定義的標記和程式碼後置檔案將會使 MSBuild 產生如下的程式碼:
Imports Microsoft.VisualBasic
Imports System ' STAThread
Imports System.Windows ' Application
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()
...
End Sub
End Class
End Namespace
using System; // STAThread
using System.Windows; // Application
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()
{
...
}
}
}
產生的程式碼會以額外的基礎架構程式碼 (包括進入點方法 Main) 來擴充您的應用程式定義。 STAThreadAttribute 屬性會套用至 Main 方法,以指出 WPF 應用程式的主要 UI 執行緒是 STA 執行緒 (此為 WPF 之所需)。呼叫 Main 時,它會在呼叫 InitializeComponent 方法以註冊事件並設定標記中實作的屬性之前,建立 App 的新執行個體。 因為 InitializeComponent 是自動產生的,所以您不需要像實作 Page 和 Window 時一樣,從應用程式定義明確呼叫 InitializeComponent。 最後,此程式碼會呼叫 Run 方法來啟動應用程式。
取得目前的應用程式
因為 Application 類別的服務會在整個應用程式中共用,所以每個 AppDomain 只能有一個 Application 類別執行個體。 為強制施行此原則,Application 類別會實作成單一類別 (請參閱在 C# 中實作單一類別);此類別可建立本身的單一執行個體,並使用 static Current 屬性提供其共用存取權。
下列程式碼顯示如何取得目前 AppDomain 之 Application 物件的參考。
' Get current application
Dim current As Application = App.Current
// Get current application
Application current = App.Current;
Current 會傳回 Application 類別執行個體的參考。 如果需要 Application 衍生類別 (Derived Class) 的參考,必須轉換 Current 屬性的值,如下列範例所示。
' Get strongly-typed current application
Dim appCurrent As App = CType(App.Current, App)
// Get strongly-typed current application
App app = (App)App.Current;
您可以在 Application 物件存留期的任何時間點檢查 Current 的值。 不過,您應該小心。 在 Application 類別具現化 (Instantiated) 之後,有一段時間 Application 物件的狀態並不一致。 在這段時間,Application 會執行執行程式碼所需的各種初始設定工作,包括建立應用程式基礎結構、設定屬性和註冊事件。 如果您在這段時間嘗試使用 Application 物件,程式碼可能會產生無法預期的結果,尤其是當程式碼相依於正在設定的各種 Application 屬性時。
在 Application 完成初始設定工作時,其存留期才會正式開始。
應用程式存留期
WPF 應用程式的存留期是由 Application 引發的幾個事件標記,讓您知道應用程式何時啟動、何時啟用並停用,以及何時關閉。
這個章節包含下列子章節。
- 開頭顯示畫面
- 啟動應用程式
- 顯示使用者介面
- 處理命令列引數
- 應用程式啟動和停用
- 應用程式關閉
- 未處理的例外狀況
- 應用程式存留期事件
開頭顯示畫面
在 .NET Framework 3.5 SP1 中進行啟動時,您可以指定要在啟動視窗或「啟動顯示畫面」(Splash Screen) 中使用影像。 SplashScreen 類別讓您可以輕易在應用程式載入時,顯示啟動視窗。 會建立 SplashScreen 視窗,並在呼叫 Run 前顯示這個視窗。 如需詳細資訊,請參閱 應用程式啟動時間 和 HOW TO:在 WPF 應用程式中加入啟動顯示畫面。
啟動應用程式
呼叫 Run 並初始化應用程式之後,執行應用程式的準備工作便已完成。 這個時間點是以引發 Startup 事件來表示:
Imports Microsoft.VisualBasic
Imports System.Windows ' Application, StartupEventArgs, WindowState
Namespace SDKSample
Partial Public Class App
Inherits Application
Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
' Application is running
...
End Sub
End Class
End Namespace
using System.Windows; // Application, StartupEventArgs, WindowState
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Application is running
...
}
}
}
在應用程式存留期的這個階段,最常執行的工作是顯示 UI。
顯示使用者介面
大部分的獨立 Windows 應用程式在開始執行時都會開啟 Window。 如下列程式碼所示範,Startup 事件處理常式是可以執行這項工作的其中一個位置。
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
Startup="App_Startup" />
Imports Microsoft.VisualBasic
Imports System.Windows ' Application, StartupEventArgs
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
using System.Windows; // Application, StartupEventArgs
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Open a window
MainWindow window = new MainWindow();
window.Show();
}
}
}
注意事項 |
---|
根據預設,獨立應用程式中所要具現化的第一個 Window 會成為主應用程式視窗。這個 Window 物件是由 Application.MainWindow 屬性所參考。如果主視窗應該是第一個具現化之 Window 以外的其他視窗,可以透過程式設計的方式變更 MainWindow 屬性的值。 |
在 XBAP 第一次啟動時,它最有可能會巡覽至 Page。 請參考下列程式碼中的示範。
<Application
x:Class="SDKSample.App"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
Startup="App_Startup" />
Imports System ' Uri, UriKind, EventArgs, Console
Imports System.Windows ' Application, StartupEventArgs
Imports System.Windows.Navigation ' NavigationWindow
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
using System; // Uri, UriKind, EventArgs, Console
using System.Windows; // Application, StartupEventArgs
using System.Windows.Navigation; // NavigationWindow
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
((NavigationWindow)this.MainWindow).Navigate(new Uri("HomePage.xaml", UriKind.Relative));
}
}
}
如果您將 Startup 處理成只開啟 Window 或巡覽至 Page,可以改為設定標記中的 StartupUri 屬性。
下列範例示範如何從獨立應用程式使用 StartupUri 開啟 Window。
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />
下列範例示範如何使用 StartupUri 從 XBAP 巡覽至 Page。
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml" />
這個標記的效果與前述用來開啟視窗的程式碼相同。
注意事項 |
---|
如需巡覽的詳細資訊,請參閱巡覽概觀。 |
在下列情況下,您必須處理 Startup 事件來開啟 Window:需要使用非預設建構函式 (Constructor) 將它具現化、需要在顯示它之前設定其屬性或訂閱其事件,或是需要處理啟動應用程式時所提供的任何命令列引數。
處理命令列引數
在 Windows 中,獨立應用程式可以從命令提示字元或桌面啟動。 在這兩種情況下,都可以將命令列引數傳遞至應用程式。下列範例顯示以單一命令列引數 "/StartMinimized" 啟動應用程式:
wpfapplication.exe /StartMinimized
在應用程式初始設定期間,WPF 會從作業系統擷取命令列引數,並透過 StartupEventArgs 參數的 Args 屬性,將它們傳遞至 Startup 事件處理常式。 您可以使用如下的程式碼擷取及儲存命令列引數。
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
Startup="App_Startup" />
Imports Microsoft.VisualBasic
Imports System.Windows ' Application, StartupEventArgs, WindowState
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
using System.Windows; // Application, StartupEventArgs, WindowState
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();
}
}
}
這個程式碼會處理 Startup,檢查是否已提供 /StartMinimized 命令列引數;如果已提供,它會使用 Minimized 的 WindowState 開啟主視窗。 請注意,因為 WindowState 屬性必須以程式設計方式設定,所以必須在程式碼中明確開啟主 Window。
XBAPs 無法擷取及處理命令列引數,因為它們是使用 ClickOnce 部署來啟動 (請參閱部署 WPF 應用程式 (WPF))。 不過,可以從啟動 URL 中擷取和處理查詢字串參數。
應用程式啟動和停用
Windows 也允許使用者在應用程式之間進行切換。最常用的方式是使用 ALT+TAB 按鍵組合。 只有在應用程式具有使用者可以選取的可見 Window 時,使用者才能切換到該應用程式。 目前選取的 Window 是「使用中視窗」(Active Window),又稱為「前景視窗」(Foreground Window),也是用來接收使用者輸入的 Window。具有使用者視窗的應用程式是「作用中應用程式」(Active Application),也稱為「前景應用程式」(Foreground Application)。在下列情況中,應用程式會變成作用中應用程式:
您可藉由處理 Application.Activated 事件,偵測應用程式變成作用中的時間。
同樣地,在下列情況中,應用程式會變成非作用中:
使用者從目前的應用程式切換到其他應用程式。
應用程式關閉時。
您可藉由處理 Application.Deactivated 事件,偵測應用程式變成非作用中的時間。
下列程式碼顯示如何處理 Activated 和 Deactivated 事件,以判斷應用程式是否正在作用。
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
Activated="App_Activated"
Deactivated="App_Deactivated" />
Imports Microsoft.VisualBasic
Imports System ' EventArgs
Imports System.Windows ' Application
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
using System; // EventArgs
using System.Windows; // Application
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;
}
}
}
Window 也可以啟動及停用。 如需詳細資訊,請參閱 Window.Activated 和 Window.Deactivated。
注意事項 |
---|
XBAPs 既不會引發 Application.Activated 也不會引發 Application.Deactivated。 |
應用程式關閉
應用程式一旦關閉,其存留期間便告結束,而應用程式關閉的可能原因包括:
為了協助您管理應用程式關閉作業,Application 提供了 Shutdown 方法、ShutdownMode 屬性,以及 SessionEnding 和 Exit 事件。
注意事項 |
---|
Shutdown 只能從擁有 UIPermission 的應用程式呼叫。獨立的 WPF 應用程式全都擁有這種使用權限。不過,執行於網際網路區域部分信任安全性沙箱的 XBAPs 並無這種使用權限。 |
程式關閉模式
大部分的應用程式都是在所有視窗關閉或主視窗關閉時便會關閉。 不過,有時候應用程式關閉的時機可能是由其他應用程式特定條件決定。 您可以使用下列其中一個 ShutdownMode 列舉值設定 ShutdownMode,藉以指定應用程式關閉的條件:
ShutdownMode 的預設值是 OnLastWindowClose,這個值表示應用程式會在使用者關閉應用程式的最後一個視窗時自動關閉。 不過,如果應用程式應該在主視窗時關閉,如果您將 ShutdownMode 設定為 OnMainWindowClose,WPF 便會自動執行該項動作。 這項巡覽功能顯示在下列範例中。
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
ShutdownMode="OnMainWindowClose" />
當您擁有應用程式特定關閉條件時,您會將 ShutdownMode 設定為 OnExplicitShutdown。 在這種情況下,您必須負責透過明確呼叫 Shutdown 方法來關閉應用程式;否則,即使所有視窗都已關閉,應用程式仍會繼續執行。 請注意,當 ShutdownMode 是 OnLastWindowClose 或 OnMainWindowClose 時,則會以隱含方式呼叫 Shutdown。
注意事項 |
---|
ShutdownMode 可以從 XBAP 設定,但是系統會忽略它;每次從瀏覽器離開時,或是裝載 (Host) XBAP 的瀏覽器關閉時,XBAP 一定都會關閉。如需詳細資訊,請參閱 巡覽概觀。 |
工作階段結束
ShutdownMode 屬性所描述的關閉條件是應用程式專屬條件。 不過在某些情況下,應用程式可能會因為外部條件而關閉。 最常見的外部條件是當使用者透過下列動作結束 Windows 工作階段時:
登出
關機
重新開機
休眠
若要偵測 Windows 工作階段何時結束,您可以處理 SessionEnding 事件,如同下列範例所示。
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
SessionEnding="App_SessionEnding" />
Imports Microsoft.VisualBasic
Imports System.Windows ' Application, SessionEndingCancelEventArgs, MessageBox, MessageBoxResult, MessageBoxButton
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
using System.Windows; // Application, SessionEndingCancelEventArgs, MessageBox, MessageBoxResult, MessageBoxButton
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;
}
}
}
}
在這個範例中,程式碼會檢查 ReasonSessionEnding 屬性,以判斷 Windows 工作階段結束的方式。 接著,它會使用這個值對使用者顯示確認訊息。 如果使用者不想結束工作階段,程式碼會將 Cancel 設定為 true,以避免結束 Windows 工作階段。
注意事項 |
---|
XBAPs 不會引發 SessionEnding。 |
Exit
當應用程式關閉時,可能需要執行某些最終處理作業,例如保存應用程式狀態。 針對這種情況,您可以處理 Exit 事件。
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
Exit="App_Exit">
...
</Application>
Imports System.IO ' StreamReader, FileMode
Imports System.IO.IsolatedStorage ' IsolatedStorageFile, IsolatedStorageFileStream
Namespace SDKSample
Partial Public Class App
Inherits Application
Private filename As String = "App.txt"
...
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
using System.Windows; // Application, StartupEventArgs
using System.IO; // StreamReader, FileMode
using System.IO.IsolatedStorage; // IsolatedStorageFile, IsolatedStorageFileStream
namespace SDKSample
{
public partial class App : Application
{
string filename = "App.txt";
...
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]);
}
}
}
}
}
如需完整的範例,請參閱 HOW TO:跨應用程式工作階段保存和還原應用程式範圍的屬性。
獨立應用程式和 XBAPs 都可以處理 Exit。 XBAPs 會在發生下列情況時引發 Exit:
離開 XBAP 時。
在 Internet Explorer 7 中關閉裝載 XBAP 的索引標籤時。
關閉瀏覽器時。
結束代碼
應用程式大多由作業系統啟動以回應使用者的要求。 不過,其他應用程式也可以啟動應用程式來執行某項特定工作。 在被啟動的應用程式關閉時,啟動端的應用程式可能需要知道被啟動之應用程式是在什麼狀況下關閉的。 在這種情況下,Windows 可以讓應用程式在關閉時傳回應用程式結束代碼 (Exit Code)。 根據預設,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="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
DispatcherUnhandledException="App_DispatcherUnhandledException" />
Imports Microsoft.VisualBasic
Imports System.Windows ' Application
Imports System.Windows.Threading ' DispatcherUnhandledExceptionEventArgs
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
using System.Windows; // Application
using System.Windows.Threading; // DispatcherUnhandledExceptionEventArgs
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;
}
}
}
DispatcherUnhandledException 事件處理常式會收到傳入的 DispatcherUnhandledExceptionEventArgs 參數,其中包含關於未處理之例外狀況的內容資訊,包括例外狀況本身 (DispatcherUnhandledExceptionEventArgs.Exception)。 您可以使用這項資訊決定處理例外狀況的方式。
處理 DispatcherUnhandledException 時,您應該將 DispatcherUnhandledExceptionEventArgs.Handled 屬性設定為 true,否則 WPF 仍會將例外狀況視為未處理,並還原成前述的預設行為。 如果已引發未處理的例外狀況,而且沒有處理 DispatcherUnhandledException 事件,或是已處理事件且 Handled 已設定為 false,應用程式會立即關閉。 此外,也不會引發其他任何 Application 事件。 因此,如果應用程式包含必須在應用程式關閉之前執行的程式碼,您就必須處理 DispatcherUnhandledException。
雖然應用程式可能因為未處理的例外狀況而關閉,但是如下節所述,應用程式通常是為了回應使用者的要求而關閉。
應用程式存留期事件
獨立應用程式和 XBAPs 並無完全相同的存留期。下圖說明獨立應用程式存留期的重要事件,並顯示這些事件的引發順序。
同樣地,下圖也說明 XBAP 存留期的重要事件,並顯示其引發順序。
其他應用程式服務
除了管理應用程式的存留期之外,Application 還提供下列各項服務:
共用應用程式範圍屬性。
共用應用程式範圍資源。
應用程式資源、內容和來源網站資料檔案。
視窗管理。
巡覽管理。
共用應用程式範圍屬性
應用程式提供 Properties 屬性以公開可跨各種應用程式共用的狀態。 以下提供使用 Properties 的範例:
' Set an application-scope property with a custom type
Dim customType As New CustomType()
Application.Current.Properties("CustomType") = customType
...
' Get an application-scope property
' NOTE: Need to convert since Application.Properties is a dictionary of System.Object
Dim customType As CustomType = CType(Application.Current.Properties("CustomType"), CustomType)
// Set an application-scope property with a custom type
CustomType customType = new CustomType();
Application.Current.Properties["CustomType"] = customType;
...
// Get an application-scope property
// NOTE: Need to convert since Application.Properties is a dictionary of System.Object
CustomType customType = (CustomType)Application.Current.Properties["CustomType"];
如需詳細資訊,請參閱下列各項:
共用應用程式範圍資源
應用程式提供 Resources 屬性,使開發人員能夠在整個應用程式中共用 UI 資源。 以下提供使用 Resources 的範例:
' Set an application-scope resource
Application.Current.Resources("ApplicationScopeResource") = Brushes.White
...
' Get an application-scope resource
Dim whiteBrush As Brush = CType(Application.Current.Resources("ApplicationScopeResource"), Brush)
// Set an application-scope resource
Application.Current.Resources["ApplicationScopeResource"] = Brushes.White;
...
// Get an application-scope resource
Brush whiteBrush = (Brush)Application.Current.Resources["ApplicationScopeResource"];
如需詳細資訊,請參閱下列各項:
應用程式資源、內容和來源網站資料檔案
WPF 應用程式可以管理幾種類型的非程式碼資料檔案,包括資源檔、內容檔以及來源網站檔案。 下列 Helper 方法可以用來載入這些類型的資料檔案:
視窗管理
Application 和 Window 具有緊密的關聯性 (Relationship)。 如您所見,應用程式的存留期可能依據其視窗的存留期而定,如 ShutdownMode 屬性所指定。 Application 會記錄哪一個視窗指定為主應用程式視窗 (Application.MainWindow),並且保存目前執行個體化的視窗清單 (Application.Windows)。
如需詳細資訊,請參閱 WPF 視窗概觀。
巡覽管理
針對具有巡覽功能 (使用 NavigationWindow 和 Frame) 的獨立應用程式或 XBAPs,Application 偵測應用程式內的任何巡覽功能,並於適當情況引發下列事件:
此外,Application 也為任何類型的應用程式提供了使用 GetCookie 和 SetCookie 建立、保存及擷取 Cookie 的功能。
如需詳細資訊,請參閱 巡覽概觀。