ここでは、外部アプリケーションを起動して、そのアプリケーションが終了するまで待機する方法について説明します。なお外部アプリケーションを起動する方法は「外部アプリケーションを起動する、ファイルを関連付けられたソフトで開く」で説明していますので、そちらをご覧ください。
Process.WaitForExitメソッドを使用することで、プロセスが終了するまで待機することができます。WaitForExitメソッドは同期的に待機するため、待機中はフリーズしたようになります。
以下の例では、"C:\test\1.txt"を開いた後、終了するまで待機しています。また、終了後、終了コードと終了時間を表示しています。
'ファイルを開いて終了まで待機する 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())
//ファイルを開いて終了まで待機する
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プロパティで分かります。
'ファイルを開く 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
//ファイルを開く 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イベントを使えば、非同期で待機することができます。ExitedイベントはProcess.EnableRaisingEventsプロパティがTrueの時だけ発生します。
Process.Exitedイベントハンドラは、何もしないと別スレッドで実行されます。そのため、マルチスレッドの知識がないと非常に危険です。Process.SynchronizingObjectプロパティにフォームを設定しておけば、そのフォームのスレッドでExitedイベントハンドラが実行されるようになりますので、だいぶ安全になります。
次の例では起動したメモ帳が閉じられるまで非同期で待機しています。Button1をクリックしてメモ帳を起動し、メモ帳が終了するとp_Exitedメソッドが呼び出されます。このコードはボタンコントロール(Button1)が配置されたフォームのクラス内に記述されているものとします。
'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
//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メソッドでプロセスを起動する場合は、3番目の引数にTrueを指定することで同期的にプロセスの終了を待機できます。この時、4番目の引数に待機する時間をミリ秒単位で指定することもできます。
'メモ帳を起動し、終了するまで最大1分間待機する Shell("""notepad.exe""", , True, 60000)