C Sharpの応用 - 外部ソフトウェア

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

外部ソフトウェアにおいて、実行ファイルを指定して起動する方法とファイルを関連付けられたソフトウェアで起動する方法を記載する。
また、外部ソフトウェアを起動して、そのソフトウェアが終了するまで待機する方法も記載する。


外部ソフトウェアの起動

外部ソフトウェアを起動するには、起動する外部ソフトウェアのパスを指定して、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]をフォームに配置するだけで実現できる。