C# Windows Formsで同じプロセス名で特定の引数が同じ場合の2重起動防止方法は?

投稿者: Anonymous

掲題の件、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();
}
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *