C Sharpの応用 - 外部ソフトウェア
概要
外部ソフトウェアにおいて、実行ファイルを指定して起動する方法とファイルを関連付けられたソフトウェアで起動する方法を記載する。
また、外部ソフトウェアを起動して、そのソフトウェアが終了するまで待機する方法も記載する。
外部ソフトウェアの起動
外部ソフトウェアを起動するには、起動する外部ソフトウェアのパスを指定して、Process
クラスのStart
メソッドを使用する。
以下の例では、メモ帳を起動している。
外部ソフトウェアが起動する時、Start
メソッドはそのプロセスを表すProcess
クラスを返す。
// メモ帳を起動する
var process = System.Diagnostics.Process.Start("notepad.exe");
Process
クラスのStart
メソッドの第2引数は、外部ソフトウェアを起動する時に使用するコマンドライン引数を指定する。
以下の例では、コマンドライン引数にテキストファイルのパスを指定してメモ帳を起動している。
// コマンドライン引数を指定してメモ帳を起動する
var process = System.Diagnostics.Process.Start("notepad.exe", @"C:\test\test.txt");
※注意
外部ソフトウェアが既に起動しており、そのプロセスが再利用された場合はnull
を返す。
例えば、Windowsフォトビューアの実体は"dllhost.exe"であるが、これは、フォトビューアの起動の有無に関わらず実行され続けている。
そのため、Process
クラスのStart
メソッドでフォトビューアを起動する時、プロセスが再利用されてnull
を返す。
ProcessStartInfoクラスを使用してProcess.Startメソッドを呼び出す
Process
クラスのStart
メソッドは、ProcessStartInfo
クラスを指定して呼び出すこともできる。
この方法を使用することで、さらに高度な設定を行い、外部ソフトウェアを起動することができる。
以下の例では、メモ帳を起動している。
// ProcessStartInfoクラスを作成する
var ProcessInfo = new System.Diagnostics.ProcessStartInfo();
// 起動する実行ファイルのパスを設定する
ProcessInfo.FileName = "notepad.exe";
// 外部ソフトウェアを起動する
var Process = System.Diagnostics.Process.Start(ProcessInfo);
コマンドライン引数を指定するには、ProcessStartInfo
クラスのArguments
プロパティを使用する。
以下の例では、コマンドライン引数にテキストファイルのパスを指定してメモ帳を起動している。
// ProcessStartInfoクラスを作成する
var ProcessInfo = new System.Diagnostics.ProcessStartInfo();
// 起動するファイルのパスを指定する
ProcessInfo.FileName = "notepad.exe";
// コマンドライン引数を指定する
ProcessInfo.Arguments = @"C:\test\test.txt";
// 外部ソフトウェアを起動する
System.Diagnostics.Process.Start(ProcessInfo);
インスタンスのProcess.Startメソッドを呼び出す
ProcessクラスのStartメソッドには、引数を持たないメソッドもある。 このメソッドの戻り値はbool型で、プロセスが起動した時にtrue、それ以外の時はfalseを返す。
以下の例では、インスタンスメソッドを使用している。
// Processオブジェクトを作成する
var Process = new System.Diagnostics.Process();
// 起動する外部ソフトウェアのパスを設定する
Process.StartInfo.FileName = "notepad.exe";
// 外部ソフトウェアを起動する
// 起動した時はtrueを返す
bool result = Process.Start();
以下の例では、ProcessクラスのStartInfoプロパティで取得できるProcessStartInfoクラスのArgumentsプロパティを使用して、
コマンドライン引数を指定している。
// Processクラスを作成する
var Process = new System.Diagnostics.Process();
// 起動する外部ソフトウェアのパスを設定する
Process.StartInfo.FileName = "notepad.exe";
// コマンドライン引数を指定する
Process.StartInfo.Arguments = @"C:\test\test.txt";
// 外部ソフトウェアを起動する
// 起動した時はtrueを返す
bool result = Process.Start();
※注意
Processクラスの静的なStartメソッドは、内部でProcessクラスを作成して、Startメソッドを呼び出す。
Startメソッドがtrueのを返す時はProcessクラス、falseを返す時はnullを返す。
ファイルを関連付けられた外部ソフトウェアで開く
ファイルを関連付けられた外部ソフトウェアで開く場合、上記のセクションの方法で実行できる。
(ただし、InteractionクラスのShellメソッドを使用する方法を除く)
以下の例では、テキストファイルを関連付けられた外部ソフトウェアで開いている。
ただし、ProcessStartInfo
クラスのUseShellExecute
プロパティがtrueである必要がある。
Process
クラスのStart
メソッドを呼び出す場合、または、ProcessStartInfo
クラスを使用してProcess
クラスのStart
メソッドを呼び出す場合は、
UseShellExecute
プロパティがfalseになる可能性もあるので注意すること。(初期値はtrueなので、意図的に変更しなければよい)
// テキストファイルを関連付けられた外部ソフトウェアで開く
var Process = System.Diagnostics.Process.Start(@"C:\test\test.txt");
※注意
Process
クラスのStart
メソッドは、
ProcessStartInfo
クラスのUseShellExecute
プロパティがtrueの時、ShellExecuteEx
メソッドを使用してプロセスを起動する。
ProcessStartInfo
クラスのUseShellExecute
プロパティがfalseの時、ProcessStartInfo
クラスのUserName
プロパティを設定する場合、
CreateProcessWithLogonW
メソッド使用して、設定していなければCreateProcess
メソッドを使用する。
Interaction
クラスのShell
メソッドは、CreateProcess
メソッドを使います。
同期して待機する
Process
クラスのWaitForExit
メソッドを使用して、外部ソフトウェアが終了するまで待機することができる。
WaitForExit
メソッドは同期して待機するため、待機中はフリーズしたようになる。
// メモ帳を起動して終了まで待機する
var process = System.Diagnostics.Process.Start("Notepad.exe");
process.WaitForExit();
引数に待機する最大時間をミリ秒単位で指定することができる。
指定した時間が経過した場合、プロセスが終了せずともWaitForExit
メソッドが終了し、次の命令に処理が移る。
なお、プロセスの終了状態は、Process
クラスのHasExited
プロパティで確認できる。
// ファイルを開く
var process = System.Diagnostics.Process.Start("Notepad.exe");
// 終了するまで10秒待機する
process.WaitForExit(10000);
// プロセスの終了状態を確認する
if (p.HasExited)
{
MessageBox.Show("終了しました。");
}
else
{
MessageBox.Show("終了していません。");
}
非同期で待機する
Process
クラスのExited
イベントハンドラを使用して、非同期で待機することができる。
Exited
イベントハンドラは、Process
クラスのEnableRaisingEvents
プロパティがTrueの時のみ発生する。
Process
クラスのExited
イベントハンドラは、何もしないと別スレッドで実行される。
そのため、マルチスレッドの知識が無いと危険であるが、Process
クラスのSynchronizingObject
プロパティにフォームを設定することで、
そのフォームのスレッドでExited
イベントハンドラが実行されるため、安全に使用できる。
以下の例では、起動したメモ帳が閉じられるまで非同期で待機している。
ボタンを押下した場合はメモ帳を起動して、メモ帳が終了するとp_Exitedメソッドを呼び出す。
// Button1のClickイベントハンドラ
private void button1_Click(object sender, System.EventArgs e)
{
// Processオブジェクトを作成する
var process = new System.Diagnostics.Process();
// 起動するファイルを指定する
process.StartInfo.FileName = "notepad.exe";
// イベントハンドラがフォームを作成したスレッドで実行されるようにする
process.SynchronizingObject = this;
// イベントハンドラの追加
process.Exited += new EventHandler(p_Exited);
// プロセスが終了した時にExitedイベントを発生させる
process.EnableRaisingEvents = true;
// プロセスを起動する
process.Start();
}
private void p_Exited(object sender, EventArgs e)
{
// プロセスが終了したときに実行される
MessageBox.Show("終了しました。");
}
上記の例では、ソースコードの記述のみで全てを設定しているが、
Visual Studioのフォームデザイナにある[ツールボックス] - [コンポーネント] - [Process]をフォームに配置するだけで実現できる。