10

オブジェクトを破棄するまで実行され続けるセカンダリプロセスを起動する.NETクラスライブラリがあります。

プログラムがメモリ内に残っていることがいくつかあるため、統合テストを追加して、オブジェクトをGC / Finalizationに失効させた場合に、そのプロセスがスピンダウンすることを確認することにしました。

ただし、プロセスはMercurialコマンドラインクライアントであり、ビルドサーバーはすでにMercurialを独自の操作の一部として実行しているため、Mercurialがテストの開始時にすでに実行されているか、テストが開始されてまだ実行されている状況を想定しています。テストが終了すると、テストではなくビルドサーバーに関連して実行されます。

ですから、私が見つけた(または見つけなかった)Mercurialクライアントが、現在実行中のクライアントだけでなく、私が開始したものであることを確認したいと思います。

だから問題はこれです:

  • 私が見ているMercurialクライアントが私のプロセスによって開始されたかどうかをどのように知ることができますか?

「見て」ということで、Process.GetProcessesメソッドの使用を検討していましたが、これは必須ではありません。

別の質問の方が良い場合は、「自分のプロセスのすべての子プロセスを見つける方法」、つまり。答えるのは簡単です、それも十分すぎるほどです。

このページを見つけました:プロセスの親プロセスIDを知るにはどうすればよいですか?、しかし、私はそれにプロセス名を付けなければならないようです。「hg」とだけ言ったら、その質問は私が探しているケースにはあいまいすぎませんか?

4

3 に答える 3

24

たまたま、指定されたプロセスIDによって生成されたすべてのプロセスを再帰的に強制終了するC#/WMIコードが少しあります。殺害は明らかにあなたが望むものではありませんが、子プロセスの発見はあなたが興味を持っているもののようです。これがお役に立てば幸いです。

    private static void KillAllProcessesSpawnedBy(UInt32 parentProcessId)
    {
        logger.Debug("Finding processes spawned by process with Id [" + parentProcessId + "]");

        // NOTE: Process Ids are reused!
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(
            "SELECT * " +
            "FROM Win32_Process " +
            "WHERE ParentProcessId=" + parentProcessId);
        ManagementObjectCollection collection = searcher.Get();
        if (collection.Count > 0)
        {
            logger.Debug("Killing [" + collection.Count + "] processes spawned by process with Id [" + parentProcessId + "]");
            foreach (var item in collection)
            {
                UInt32 childProcessId = (UInt32)item["ProcessId"];
                if ((int)childProcessId != Process.GetCurrentProcess().Id)
                {
                    KillAllProcessesSpawnedBy(childProcessId);

                    Process childProcess = Process.GetProcessById((int)childProcessId);
                    logger.Debug("Killing child process [" + childProcess.ProcessName + "] with Id [" + childProcessId + "]");
                    childProcess.Kill();
                }
            }
        }
    }
于 2011-08-25T11:13:33.210 に答える
7

mtijnの答えはおそらくあなたが得ることができる最も近いものですが、本当の答えは:あなたはできないということです。

Windowsは、中間レベルのプロセスが停止したときにプロセスが再構築される実際のプロセスツリーを維持しません。ただし、Windowsは親プロセスIDを記憶しています。

問題のあるケースは次のとおりです。

元のプロセス構造:

YourApp.exe
- SubApp.exe
  - Second.exe

SubApp.exeが終了した場合、Second.exeの親プロセスIDは更新されません。新しい結果は

YourApp.exe
Second.exe

これは、 SysInternalsProcessExplorerを使用して確認できます。プロセスをツリーとして表示することができます。CMDを起動し、「。」と入力しstart cmdます。新しいウィンドウに、start cmdもう一度入力します。3つのウィンドウが開きます。真ん中のものを終了します。

于 2017-11-13T22:55:12.793 に答える
1

ありがとう!以前のKillAllProcessesSpawnedByAnswerから私はこれを作成しました:

        public static void WaitForAllToExit(this Process process)
        {
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(
                "SELECT * " +
                "FROM Win32_Process " +
                "WHERE ParentProcessId=" + process.Id);
            ManagementObjectCollection collection = searcher.Get();
            if (collection.Count > 0)
            {
                foreach (var item in collection)
                {
                    UInt32 childProcessId = (UInt32)item["ProcessId"];
                    if ((int)childProcessId != Process.GetCurrentProcess().Id)
                    {
                        Process childProcess = Process.GetProcessById((int)childProcessId);
                        WaitForAllToExit(childProcess);
                    }
                }
            }

            process.WaitForExit();

        }
于 2021-04-23T18:32:53.853 に答える