アプリケーション管理の概要

すべてのアプリケーションは、アプリケーションの実装と管理に適用される機能を共有することがよくあります。 このトピックでは、アプリケーションの作成と管理のための Application クラスの機能の概要について説明します。

Application クラス

WPF では、共通のアプリケーション スコープの機能は、Application クラスにカプセル化されます。 Application クラスには、次の機能が含まれています。

  • アプリケーションの有効期間を追跡し、相互作用する。

  • コマンド ライン パラメーターを取得し、処理する。

  • 未処理の例外を検出し、応答する。

  • アプリケーション スコープのプロパティと リソースを共有する。

  • スタンドアロン アプリケーションのウィンドウを管理する。

  • ナビゲーションを追跡し、管理する。

アプリケーションのクラスを使用して一般的なタスクを実行する方法

Application クラスのすべての詳細に興味がない場合は、Application の一般的なタスクとそれらを実行する方法を示す次の表を参照してください。 関連する API とトピックを表示することによって、詳細情報とサンプル コードを参照できます。

タスク 方法
現在のアプリケーションを表すオブジェクトを取得する Application.Current プロパティを使用します。
起動画面をアプリケーションに追加する スプラッシュ スクリーンを WPF アプリケーションに追加する」を参照してください。
アプリケーションを起動する Application.Run メソッドを使用します。
アプリケーションを停止する Shutdown オブジェクトの Application.Current メソッドを使用します。
コマンド ラインから引数を取得する Application.Startup イベントを処理し、StartupEventArgs.Args プロパティを使用します。 例については、Application.Startup を参照してください。
アプリケーションの終了コードを取得し、設定する Application.Exit イベント ハンドラーの ExitEventArgs.ApplicationExitCode プロパティを設定するか、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 により、x:Class 属性で指定された名前を持つ、Application から派生した partial クラスが作成されます。 そのためには、XAML スキーマ (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml") に XML 名前空間宣言を追加する必要があります。

  • 分離コードでは、クラスは、マークアップ内の x:Class 属性で指定されている名前を持つ partial クラスでなければなりません。また、Application から派生する必要があります。 これによって、分離コード ファイルと、アプリケーションのビルド時にマークアップ ファイル用に生成される partial クラスとが関連付けられます (「WPF アプリケーションのビルド」を参照)。

注意

Visual Studio を使用して新しい WPF アプリケーション プロジェクトまたは WPF ブラウザー アプリケーション プロジェクトを作成すると、アプリケーション定義が既定で含まれ、マークアップと分離コードの両方を使用して定義されます。

このコードは、アプリケーション定義を実装するために最低限必要です。 ただし、アプリケーションをビルドして実行する前に、アプリケーション定義に対して MSBuild の追加構成を行う必要があります。

MSBuild 用のアプリケーション定義の構成

スタンドアロン アプリケーションや XAML ブラウザー アプリケーション (XBAP) を実行できるようにするには、一定レベルのインフラストラクチャの実装が必要です。 このインフラストラクチャの最も重要な部分は、エントリ ポイントです。 ユーザーがアプリケーションを起動するとき、オペレーティング システムはエントリ ポイントを呼び出します。これは、アプリケーションを起動するための、よく知られている機能です。

警告

XBAP が動作するには、インターネット エクスプローラーや Firefox などの従来のブラウザーが必要です。 これらの古いブラウザー バージョンは、通常、Windows 10 や Windows 11 ではサポートされていません。 最新のブラウザーでは、セキュリティ リスクがあるため XBAP アプリに必要なテクノロジがサポートされなくなりました。 XBAP を有効にするプラグインはサポートされなくなりました。

従来、開発者は、テクノロジに応じて、このコードの一部または全部を自分で記述する必要がありました。 しかし、WPF では、次の MSBuild プロジェクト ファイルに示されているように、アプリケーション定義のマークアップ ファイルが MSBuild の ApplicationDefinition 項目として構成されると、このコードが自動生成されます。

<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

生成されるコードにより、アプリケーション定義に追加のインフラストラクチャのコードが追加され、そこに Main というエントリ ポイント メソッドが含まれます。 STAThreadAttribute 属性が Main メソッドに適用されて、WPF アプリケーションのメイン UI スレッドが、WPF アプリケーションに必須の STA スレッドであることが示されます。 呼び出されると、Main では、App の新しいインスタンスが作成されてから、InitializeComponent メソッドが呼び出されて、イベントが登録され、マークアップで実装されるプロパティが設定されます。 InitializeComponent は自動的に生成されるので、PageWindow の実装のように、アプリケーション定義から InitializeComponent を明示的に呼び出す必要はありません。 最後に、Run メソッドが呼び出されて、アプリケーションが起動されます。

現在のアプリケーションの取得

Application クラスの機能はアプリケーション間で共有されるため、Application クラスのインスタンスは、AppDomain ごとに 1 つだけです。 これを強制するため、Application クラスはシングルトン クラスとして実装されます (「C# でのシングルトンの実装」を参照)。つまり、インスタンスが 1 つだけ作成され、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)

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>

アプリケーションの有効期間中のこの時点で最も一般的に行われるのは、UI の表示です。

ユーザー インターフェイスの表示

ほとんどのスタンドアロン Windows アプリケーションでは、実行を開始するとき、Window が開かれます。 次のコードに示されているように、Startup イベント ハンドラーは、これを行うことができる場所の 1 つです。

<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 プロパティによって参照されます。 最初にインスタンス化された 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" />

このマークアップは、ウィンドウを開くことについて、前のコードと同じ効果があります。

注意

ナビゲーションの詳細については、「ナビゲーションの概要」を参照してください。

パラメーターなしではないコンストラクターを使用してウィンドウをインスタンス化する必要がある場合、またはウィンドウを表示する前にウィンドウのプロパティを設定するか、イベントをサブスクライブする必要がある場合、またはアプリケーションの起動時に指定されたコマンド ライン引数を処理する必要がある場合、Window を開くには、Startup イベントを処理する必要があります。

コマンド ライン引数の処理

Windows では、スタンドアロン アプリケーションは、コマンド プロンプトまたはデスクトップから起動できます。 どちらの場合も、コマンド ライン引数をアプリケーションに渡すことができます。 次の例は、1 つのコマンド ライン引数 "/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 コマンド ライン引数が指定されたかどうかが確認されます。指定されている場合は、WindowStateMinimized にしてメイン ウィンドウが開かれます。 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.ActivatedApplication.Deactivated も、XBAP については発生しません。

アプリケーションのシャットダウン

アプリケーションの有効期間は、シャット ダウンされると終了します。シャットダウンは、次の理由で発生します。

  • ユーザーがすべての Window を閉じた。

  • ユーザーがメイン Window を閉じた。

  • ユーザーがログオフまたはシャットダウンして、Windows セッションを終了した。

  • アプリケーション固有の条件が満たされた。

アプリケーションのシャット ダウンの管理を支援するために、Application には、Shutdown メソッド、ShutdownMode プロパティ、SessionEnding イベント、Exit イベントが用意されています。

注意

Shutdown は、UIPermission を持つアプリケーションからのみ呼び出すことができます。 スタンドアロン WPF アプリケーションには、常にこのアクセス許可があります。 一方、インターネット ゾーン部分信頼セキュリティ サンド ボックスで実行される XBAP には、このアクセス許可がありません。

シャットダウン モード

ほとんどのアプリケーションは、すべてのウィンドウが閉じられるか、メイン ウィンドウが閉じられたときにシャットダウンします。 ただし、場合によっては、他のアプリケーションに固有の条件によって、アプリケーションがシャット ダウンするタイミングに影響します。 ShutdownMode に次のいずれかの ShutdownMode 列挙値を設定することによって、アプリケーションがシャットダウンする条件を指定できます。

ShutdownMode の既定値は OnLastWindowClose であり、アプリケーションの最後のウィンドウがユーザーによって閉じられたときにアプリケーションが自動的にシャットダウンすることを意味します。 一方、メイン ウィンドウが閉じられたときにアプリケーションがシャットダウンするようにする必要がある場合は、ShutdownModeOnMainWindowClose に設定すると、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" />

アプリケーション固有のシャットダウン条件があるときは、ShutdownModeOnExplicitShutdown に設定します。 この場合、明示的に Shutdown メソッドを呼び出すことによってアプリケーションをシャット ダウンする必要があります。そうしないと、すべてのウィンドウが閉じられた場合でも、アプリケーションは実効を続けます。 Shutdown は、ShutdownModeOnLastWindowClose または 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 セッションの終了方法を決定します。 この値を使用して、ユーザーに確認メッセージを表示します。 ユーザーがセッションの終了を意図していない場合、コードでは Canceltrue に設定して、Windows セッションが終了しないようにします。

注意

SessionEnding は、XBAP に対しては発生しません。

終了

アプリケーションがシャット ダウンするときには、アプリケーション状態の保存など、いくつかの最終処理を実行しなければならない場合があります。 このような状況では、次の例の App_Exit イベント ハンドラーで行われているように、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.Exception) も含め、未処理の例外に関するコンテキスト情報を含む DispatcherUnhandledExceptionEventArgs パラメーターが渡されます。 この情報を使用して、例外の処理方法を決定できます。

DispatcherUnhandledException を処理するときには、DispatcherUnhandledExceptionEventArgs.Handled プロパティを true に設定する必要があります。そうしないと、WPF は例外を未処理のままとみなし、前述の既定の動作に戻ります。 ハンドルされない例外が発生し、DispatcherUnhandledException イベントが処理されないか、イベントが処理されても、Handledfalse に設定されていた場合、アプリケーションはただちにシャットダウンします。 さらに、他の Application イベントは発生しません。 結果として、アプリケーションに、アプリケーションがシャットダウンする前に実行しなければならないコードがある場合は、DispatcherUnhandledException を処理する必要があります。

アプリケーションは、未処理の例外の結果としてシャットダウンすることがありますが、通常は、次のセクションで説明されているように、ユーザーの要求に応じてシャットダウンします。

アプリケーションの有効期間イベント

スタンドアロン アプリケーションと XBAP の有効期間は、厳密に同じわけではありません。 次の図は、スタンドアロン アプリケーションの有効期間中の主なイベントと発生順を示しています。

Standalone Application - Application Object Events

同様に、次の図では、XBAP の有効期間中の主なイベントと発生順を示します。

XBAP - Application Object Events

関連項目