質問: 掲題の件、C#で同じWindows Formsのexeで特定の引数が同じ場合に2重起動を防止したいのですが 可能でしょうか? 例) 「A.exe argA argB」を起動中に以下の要件を満たしたい。 A.exe argC argD は、起動OK A.exe argA argE は、起動NG 引数は必ず指定されるものとします。引数が不足している場合は、起動エラーにします。 arg[0]が文字列として完全一致した場合に、2重起動を抑止したいです。 具体的な、要件ですが、Windows Formsの画面をメニューから 同じランチャ(A.exe)を使って、異なるForm画面を起動しようとしています。 (A.exeが異なる引数で複数のプロセスとして起動することになります。) その際に、同じアプリコードの画面の場合に起動を抑止したいです。 何かアドバイス頂ければと思います。 よろしくお願いいたします。
回答: 他プロセスのコマンドライン引数はWMIで取得できますので、起動時に排他をかけつつ値を検証すればよいのでは。 ``` [STAThread] private static void Main(string[] args) { var cp = Process.GetCurrentProcess(); Console.WriteLine($"PID:{cp.Id}"); for (var i = 0; i < args.Length; i++) { Console.WriteLine($" - {i}: {args[i]}"); } var mutex = new Mutex(false, typeof(Program).FullName); try { Console.WriteLine("Entering Mutex"); mutex.WaitOne(); var pn = cp.ProcessName + ".exe"; using (var mc = new ManagementClass("Win32_Process")) { foreach (var op in mc.GetInstances()) { if (pn.Equals(op["Name"] as string, StringComparison.InvariantCultureIgnoreCase)) { var pid = Convert.ToInt32(op["ProcessId"]); if (pid == cp.Id) { continue; } var cmd = op["CommandLine"] as string; // TODO:コマンドライン引数は""でエスケープできるのできちんと解析する必要がある var otherArgs = cmd.Split(' ') // 先頭は実行ファイルのため飛ばす .Skip(1) .ToArray(); Console.WriteLine($"PID:{pid}"); for (var i = 0; i < otherArgs.Length; i++) { Console.WriteLine($" - {i}: {otherArgs[i]}"); } // 引数が被っていたら終了 if (args.Intersect(otherArgs).Any()) { Console.WriteLine("Already exists"); return; } } } }; } finally { mutex.ReleaseMutex(); Console.WriteLine("Exit Mutex"); } // TODO: 実際の起動処理を入れる。 // Application.EnableVisualStyles(); // Application.SetCompatibleTextRenderingDefault(false); // Application.Run(new Form1()); Console.WriteLine("Hit any key to exit..."); Console.ReadKey(); } ```