この記事では外部アプリを起動する方法、終了を待機する方法を紹介します。
C#のプログラムから他のアプリケーションを起動するには、名前空間System.DiagnosticsにあるProcessクラスを使います。また、StartInfoプロパティを使ってアプリを起動する際のパラメータを細かく指定することもできます。
起動するだけの場合
他のアプリを起動するだけ(他アプリの終了を待たない)ならProcessクラスの静的メソッド(static)のStartメソッドを使うと簡単です。
using System.Diagnostics;
namespace TestProject;
class Program {
static void Main(string[] args)
{
//メモ帳を起動
Process.Start("notepad");
//メモ帳に開きたいファイルパスを渡して起動
Process.Start("notepad", "test.txt");
}
}
第1引数に起動したいアプリケーションのファイルパス(フルパスやプログラムからの相対パス)を指定します。
外部アプリに引数を渡したい場合は第2引数を指定します。
引数を複数渡したい場合は半角スペースで区切って指定します。引数自体にスペースがある場合は文字列型の配列に入れて渡すとエスケープ文字を使って書かなくていいので簡単です。
//引数を複数渡したい場合は半角スペースで区切る
Process.Start("test.exe", "param1 param2");
//引数にスペースがある場合は配列に入れて渡すと簡単
Process.Start("test.exe", new string[] { "param1", "p a r a m 2" });
起動して終了するまで待機する場合
外部アプリを起動して終了するまで待機するには、ProcessクラスのインスタンスにあるWaitForExitメソッドを使います。起動する外部アプリの情報はProcessクラスのStartInfoプロパティに設定します。
Startメソッドで外部アプリを起動し、WaitForExitメソッドで外部アプリが終了するまで待機(プログラムがストップ)します。
また、起動したアプリの終了の待機後、ExitCodeプロパティから終了コードを取得できます。これを使って起動したアプリがちゃんと動いたか判定することができます。
GUI(デスクトップアプリ)から外部アプリを起動する場合でプログラムを止めたくない(画面をフリーズさせない)時は後述の非同期で待機する場合を見てください。
using System.Diagnostics;
namespace TestProject;
class Program {
static void Main(string[] args)
{
//Processクラスのインスタンスを作成
using Process proc = new Process();
//起動したい外部アプリの情報を設定
proc.StartInfo.FileName = "notepad"; //起動したい実行ファイルのパス
proc.StartInfo.Arguments = ""; //起動したい実行ファイルに渡すパラメータ
//外部アプリ起動
proc.Start();
//外部アプリの終了を待機する
proc.WaitForExit();
//外部アプリの終了コードを表示
Console.WriteLine(proc.ExitCode);
}
}
起動して終了するまで非同期で待機する場合
ProcessクラスにあるWaitForExitAsyncメソッドを使うと外部アプリの終了待機を非同期で行うことができます。このメソッドはデスクトップアプリで外部アプリの終了待機中に画面がフリーズしないようにするのに使えます。
サンプルとして、画面のボタンがクリックされるとメモ帳が起動され、メモ帳が開いている最中は画面のボタンが無効化され押せなくなり、メモ帳が閉じられるとボタンが有効化され押せるようになるというものを作ってみました。
以下のコードのbtnStart_Clickメソッドは画面のボタンがクリックされたときに呼ばれるメソッドの抜粋です。メソッド内でawaitというキーワードを使っているので、メソッドのシグネチャにasyncというキーワードを付けて非同期メソッドになっています。
14行目「await proc.WaitForExitAsync」のところで一旦制御が呼び出し元に戻ってくるので画面がフリーズすることがなくなります。外部アプリが終了すると次の行(17行目)から処理が再開されます。
using System.Diagnostics;
//-- 中略 --//
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
//ボタンを無効化
this.btnStart.IsEnabled = false;
//Processのインスタンスを作成して外部アプリの情報を設定して起動
using Process proc = new Process();
proc.StartInfo.FileName = "notepad.exe";
proc.Start();
//外部アプリの終了を非同期で待機
await proc.WaitForExitAsync();
//ボタンを有効化
this.btnStart.IsEnabled = true;
}
非同期メソッドについてはこちらの記事で詳しく紹介しています。
Mainメソッドでも非同期っぽく
Mainメソッドでも外部アプリの終了を待機しつつ他の処理をしたい、という場合はStartメソッドとWaitForExitメソッドの間に処理を書くとそれっぽくなります。
正確には外部アプリ起動後になんか処理をしてから外部アプリを終了を待つという感じです。
using System.Diagnostics;
namespace TestProject;
class Program {
static void Main(string[] args)
{
//Processクラスのインスタンスを作成
using Process proc = new Process();
//起動したい外部アプリの情報を設定
proc.StartInfo.FileName = "notepad"; //起動したい実行ファイルのパス
proc.StartInfo.Arguments = ""; //起動したい実行ファイルに渡すパラメータ
//外部アプリ起動
proc.Start();
//-- ここに待機する前にやる処理を書く
//外部アプリの終了を待機する
proc.WaitForExit();
//外部アプリの終了コードを表示
Console.WriteLine(proc.ExitCode);
}
}
コンソールアプリ起動時にコンソール画面を非表示にする
デフォルトの設定でデスクトップアプリからコンソールアプリを起動するとコンソール画面(黒い画面)が表示されます。
これを表示しないようにするにはProcessクラスのStartInfoプロパティのCreateNoWindowプロパティをtrueに設定します。
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
//ボタンを無効化
this.btnStart.IsEnabled = false;
//Processのインスタンスを作成して外部アプリの情報を設定して起動
using Process proc = new Process();
proc.StartInfo.FileName = "test.exe";
proc.StartInfo.CreateNoWindow = true; //コンソール画面を表示しない
proc.Start();
//外部アプリの終了を非同期で待機
await proc.WaitForExitAsync();
//ボタンを有効化
this.btnStart.IsEnabled = true;
}
StartInfoプロパティには他にもいろいろな項目があります。気になる方はMisrosoft公式ページを見てください。
C# 記事まとめページに戻る(他のサンプルコードもこちら)
コメント