子プロセスを起動する際のコマンドライン引数は、ProcessStartInfoクラスのArgumentsプロパティで指定することができます。 ただし、このプロパティは引数すべてを単一の文字列として指定する必要があり、また空白
を含む文字列とダブルクオーテーション"
のエスケープが必要な場合はエスケープ済みの文字列を指定する必要があります。
.NET Standard 2.1/.NET Core 2.1以降では、ArgumentListプロパティを使用することもできます。 このプロパティは引数を文字列のコレクションとして指定することができ、また空白
を含む文字列とダブルクオーテーション"
のエスケープも自動的に行われます。
コマンドライン引数はArgumentsまたはArgumentListのどちらか一方のみが設定でき、両方設定した状態でProcess.Startメソッドを呼び出すとInvalidOperationExceptionをスローします。 また、Argumentsに設定した値はArgumentListには反映されず、逆もまた同様です。
ProcessStartInfoクラスで子プロセスのコマンドライン引数を指定する
using System;
using System.Diagnostics;
class Sample {
static void Main(string[] args)
{
// 子プロセスとして起動された場合は、コマンドライン引数を一行ごとに表示して終了する
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CHILD"))) {
foreach (var arg in args) {
Console.WriteLine(arg);
}
return;
}
// 自プロセスと同じ実行可能ファイルに、コマンドライン引数を与えて子プロセスとして起動する
var psi = new ProcessStartInfo(Process.GetCurrentProcess().MainModule.FileName) {
#if true
// Argumentsプロパティでコマンドライン引数を指定する
Arguments = @"/esc=\"" /dir1=C:\Program Files\dotnet /dir2=""C:\Program Files\dotnet"" ""/dir3 = C:\Program Files\dotnet""",
#else
// ArgumentListプロパティでコマンドライン引数を指定する
ArgumentList = {@"/esc=""", @"/dir1=C:\Program Files\dotnet", @"/dir2=""C:\Program Files\dotnet""", @"""/dir3 = C:\Program Files\dotnet"""},
#endif
EnvironmentVariables = { {"CHILD", "1"} }, // 子プロセスとして起動したことを示す環境変数を設定しておく (再帰的なプロセス生成を抑止する)
UseShellExecute = false, // ⚠.NET Core/.NET 5以降ではデフォルトでfalseとなっているため、明示的に指定しなくても可
};
// 上記のパラメータで子プロセスを起動する
using (var child = Process.Start(psi)) {
// 子プロセスの終了を待機する
child.WaitForExit();
}
}
}
実行結果
/esc=" /dir1=C:\Program Files\dotnet /dir2=C:\Program Files\dotnet /dir3 = C:\Program Files\dotnet
実行結果
/esc=" /dir1=C:\Program Files\dotnet /dir2="C:\Program Files\dotnet" "/dir3 = C:\Program Files\dotnet"
上記のコードでは、コマンドライン引数を与えた上で再帰的にプロセスを起動しています。 上記のコードで環境変数CHILD
を指定せずに実行した場合Fork爆弾と同様の動作となるため、コードを改変する場合は注意してください。