動作確認環境: .NET Framework 3.5、Visual Studio 2010、Windows 7、Windows API Code Pack 1.1

更新日: 2010 年 11 月 12 日

執筆者: マイクロソフト株式会社
デベロッパー エバンジェリスト
田中達彦

Windows 7 や Windows Vista には、アプリケーションが予期せぬクラッシュで終了してしまったときに、アプリケーションが保持しているデータを保存できるようにする機能があります。

Windows API Code Pack を使用すると、このアプリケーションの再起動と修復の機能を実装できます。

本サンプルは、Windows フォームを使用したアプリケーションで説明します。

Visual Studio を使用して Windows フォーム アプリケーションを作成し、フォーム上に Button コントロールと TextBox コントロールを下図のように貼り付けてください。テキストボックスの Multiline プロパティは true に変更しておきます。

Windows API Code Pack で提供している機能を使用するので、Visual Studio のメニューより [プロジェクト] - [参照の追加] を選択し、[参照] タブより Windows API Code Pack で提供している Microsoft.WindowsAPICodeaPack.dll への参照を追加してください。

クラッシュ時にデータを保存させるために、データを保存するための修復用メソッドの実装と、そのメソッドがクラッシュ時に呼び出されるように登録しておくことが必要です。
クラッシュによってアプリケーションが再起動された際、そのアプリケーションが正常に起動されたのか、クラッシュによって再起動されたのかを見分ける必要があります。その判別には、コマンドライン オプションを使用します。クラッシュ時の再起動時のみに特定の文字列をコマンドライン オプションとして指定することにより、通常の起動との判別を行うことができます。

これらの機能を実装すると、下記のプログラムになります。下記プログラム中の、Form1_Load の部分は、Visual Studio 上にフォームを表示させ、フォーム上の何も貼り付けていない部分をダブルクリックして作成してください。何も貼り付けていない部分をダブルクリックすることにより、Private Sub Form1_Load で始まるイベント ハンドラーが自動的に生成されます。

Visual Basic
' Windows API Code Pack への参照
Imports Microsoft.WindowsAPICodePack.ApplicationServices
' ファイルの読み書きで使用
Imports System.IO

Public Class Form1
    ' データを一時的に保存しておくフィールド
    Private TextData As String = ""

    ' クラッシュ時に、一時的にデータを書き込んでおくファイル名
    ' ここでは、一時的はファイル名として適切なものを指定する
    Private RecoveryFile As String = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "AppRestartRecoveryDemoData.txt")

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' アプリケーションの再起動時に渡されるコマンドラインオプションの指定
        ApplicationRestartRecoveryManager.RegisterForApplicationRestart(New RestartSettings("/restart", RestartRestrictions.NotOnReboot Or RestartRestrictions.NotOnPatch))

        ' クラッシュ時に自動的に呼ばれる修復用メソッドの登録
        Dim data As New RecoveryData(New RecoveryCallback(AddressOf RecoveryProcedure), Nothing)
        Dim settings As New RecoverySettings(data, 0)
        ApplicationRestartRecoveryManager.RegisterForApplicationRecovery(settings)

        ' 起動時の、クラッシュによる再起動かどうかの判断
        If System.Environment.GetCommandLineArgs().Length > 1 AndAlso System.Environment.GetCommandLineArgs()(1) = "/restart" Then
            ' クラッシュによる再起動だった場合は、ファイルに保存したデータを復元する
            If (File.Exists(RecoveryFile)) Then
                ' 指定したファイルからデータを読み込む
                TextBox1.Text = File.ReadAllText(RecoveryFile)
            End If
        End If
    End Sub

    ' クラッシュ時に自動的に呼び出される修復用メソッド
    Private Function RecoveryProcedure(ByVal state As Object) As Integer
        ' 指定したファイルにデータを書き込む
        File.WriteAllText(RecoveryFile, TextData)

        ApplicationRestartRecoveryManager.ApplicationRecoveryFinished(True)
        Return 0
    End Function
End Class
 

本サンプル プログラムでは、テキストボックスの中に入力されている文字をクラッシュ時に復元します。テキストボックスのようなコントロールに保持されている情報はクラッシュ時に読み取ることができないため、テキストボックスに入力されたデータを、文字を入力するごとに用意していたフィールドに格納します。

フォーム上のテキストボックスをダブルクリックし、自動的に生成される以下のイベント ハンドラーにそのコードを実装します。

Visual Basic
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
    TextData = TextBox1.Text
End Sub
 

ここまでで、予期せぬクラッシュ時におけるアプリケーションの再起動と修復の実装は完了しました。

しかし、このままだとクラッシュのテストができないため、フォーム上のボタンをダブルクリックし、生成されたイベント ハンドラーに以下のコードを実装します。

Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Environment.FailFast("強制終了")
End Sub
 

これで、ボタンをクリックするとアプリケーションがクラッシュします。

本サンプル プログラムを試す際には、Visual Studio 上の [デバッグなしで開始] を選択してプログラムを実行してください。デバッグ付きで実行すると、アプリケーションのクラッシュを Visual Studio が拾ってしまうので、プログラムの動きを試すことができません。また、実行後 60 秒間は、クラッシュさせても再起動と修復の機能が仕様により働きません。アプリケーションの起動後 60 秒以上経過してから、アプリケーションをクラッシュさせてください。

上記の全ての機能を実装したら、アプリケーションを起動して文字を入力し、60 秒経過してからボタンをクリックしてください。


Code Recipe Code Recipe

ページのトップへ