DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

外部アプリケーションを起動して終了まで待機する

ここでは、外部アプリケーションを起動して、そのアプリケーションが終了するまで待機する方法について説明します。なお外部アプリケーションを起動する方法は「外部アプリケーションを起動する、ファイルを関連付けられたソフトで開く」で説明していますので、そちらをご覧ください。

WaitForExitメソッドを使って同期的に待機する

Process.WaitForExitメソッドを使用することで、プロセスが終了するまで待機することができます。WaitForExitメソッドは同期的に待機するため、待機中はフリーズしたようになります。

以下の例では、"C:\test\1.txt"を開いた後、終了するまで待機しています。また、終了後、終了コードと終了時間を表示しています。

VB.NET
コードを隠すコードを選択
'ファイルを開いて終了まで待機する
Dim p As System.Diagnostics.Process = _
    System.Diagnostics.Process.Start("C:\test\1.txt")
p.WaitForExit()

MessageBox.Show("終了しました。" & _
    vbLf & "終了コード:" & p.ExitCode.ToString() & _
    vbLf & "終了時間:" & p.ExitTime.ToString())
C#
コードを隠すコードを選択
//ファイルを開いて終了まで待機する
System.Diagnostics.Process p =
    System.Diagnostics.Process.Start("C:\\test\\1.txt");
p.WaitForExit();

MessageBox.Show("終了しました。" +
    "\n終了コード:" + p.ExitCode.ToString() +
    "\n終了時間:" + p.ExitTime.ToString());

上記の例ではプロセスが終了するまでずっと待機していますが、引数に待機する最大時間をミリ秒単位で指定することもできます。指定した時間が経過すると、プロセスが終了していなくてもWaitForExitメソッドが終了し、次の命令に処理が移ります。なおプロセスが終了したかは、Process.HasExitedプロパティで分かります。

VB.NET
コードを隠すコードを選択
'ファイルを開く
Dim p As System.Diagnostics.Process = _
    System.Diagnostics.Process.Start("C:\test\1.txt")
'終了するまで最大10秒間だけ待機する
p.WaitForExit(10000)
'終了したか確認する
If p.HasExited Then
    MessageBox.Show("終了しました。")
Else
    MessageBox.Show("終了していません。")
End If
C#
コードを隠すコードを選択
//ファイルを開く
System.Diagnostics.Process p =
    System.Diagnostics.Process.Start("C:\\test\\1.txt");
//終了するまで最大10秒間だけ待機する
p.WaitForExit(10000);
//終了したか確認する
if (p.HasExited)
{
    MessageBox.Show("終了しました。");
}
else
{
    MessageBox.Show("終了していません。");
}

Process.Exitedイベントを使って非同期で待機する

Process.Exitedイベントを使えば、非同期で待機することができます。ExitedイベントはProcess.EnableRaisingEventsプロパティがTrueの時だけ発生します。

Process.Exitedイベントハンドラは、何もしないと別スレッドで実行されます。そのため、マルチスレッドの知識がないと非常に危険です。Process.SynchronizingObjectプロパティにフォームを設定しておけば、そのフォームのスレッドでExitedイベントハンドラが実行されるようになりますので、だいぶ安全になります。(詳しくは、こちらをご覧ください。)

次の例では起動したメモ帳が閉じられるまで非同期で待機しています。Button1をクリックしてメモ帳を起動し、メモ帳が終了するとp_Exitedメソッドが呼び出されます。このコードはボタンコントロール(Button1)が配置されたフォームのクラス内に記述されているものとします。

VB.NET
コードを隠すコードを選択
'Button1のClickイベントハンドラ
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles Button1.Click
    'Processオブジェクトを作成する
    Dim p As New System.Diagnostics.Process()
    '起動するファイルを指定する
    p.StartInfo.FileName = "notepad.exe"
    'イベントハンドラがフォームを作成したスレッドで実行されるようにする
    p.SynchronizingObject = Me
    'イベントハンドラの追加
    AddHandler p.Exited, New EventHandler(AddressOf p_Exited)
    'プロセスが終了したときに Exited イベントを発生させる
    p.EnableRaisingEvents = True
    '起動する
    p.Start()
End Sub

Private Sub p_Exited(ByVal sender As Object, ByVal e As EventArgs)
    'プロセスが終了したときに実行される
    MessageBox.Show("終了しました。")
End Sub
C#
コードを隠すコードを選択
//Button1のClickイベントハンドラ
private void button1_Click(object sender, System.EventArgs e)
{
    //Processオブジェクトを作成する
    System.Diagnostics.Process p = new System.Diagnostics.Process();
    //起動するファイルを指定する
    p.StartInfo.FileName = "notepad.exe";
    //イベントハンドラがフォームを作成したスレッドで実行されるようにする
    p.SynchronizingObject = this;
    //イベントハンドラの追加
    p.Exited += new EventHandler(p_Exited);
    //プロセスが終了したときに Exited イベントを発生させる
    p.EnableRaisingEvents = true;
    //起動する
    p.Start();
}

private void p_Exited(object sender, EventArgs e)
{
    //プロセスが終了したときに実行される
    MessageBox.Show("終了しました。");
}

上の例ではコードだけですべて行っていますが、Visual Studioのフォームデザイナを使用すれば、「ツールボックス」の「コンポーネント」タブにある「Process」をフォームに配置するだけで実現することもできます。

VB.NETでInteraction.Shellメソッドを使う場合

VB.NETのInteraction.Shellメソッドでプロセスを起動する場合は、3番目の引数にTrueを指定することで同期的にプロセスの終了を待機できます。この時、4番目の引数に待機する時間をミリ秒単位で指定することもできます。

VB.NET
コードを隠すコードを選択
'メモ帳を起動し、終了するまで最大1分間待機する
Shell("""notepad.exe""", , True, 60000)
  • 履歴:
  • 2010/10/14 「起動したアプリケーションが終了するまで待機する」のコードを修正。
  • 2013/7/4 Windowsフォトビューアーの終了を待機できない理由を追記。
  • 2013/7/14 「起動したアプリケーションが終了するまで待機する」のサンプルに終了コードと終了時間を表示する例と、指定時間だけ待機する例を追加。
  • 2013/9/8 「外部アプリケーションを起動する、ファイルを関連付けられたソフトで開く」だけの方法を別ページに移動。「Interaction.Shellメソッドを使う場合」を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。