查找我自己的.NET进程的所有子进程/查找给定进程是否是我自己的子进程?

查找我自己的.NET进程的所有子进程/查找给定进程是否是我自己的子进程?,.net,process,child-process,.net,Process,Child Process,我有一个.NET类库,它可以启动一个辅助进程,该进程将一直运行,直到我处理完对象为止 由于程序在内存中出现了一些延迟,我决定添加一个集成测试,以确保如果我让对象进入GC/终结,该过程将停止 但是,由于该进程是Mercurial命令行客户端,并且我的构建服务器已经在运行Mercurial作为其自身操作的一部分,因此我设想的情况是,Mercurial在测试启动时已经运行,或者在测试结束时,它已经启动,并且仍然在运行,与构建服务器相关,而不是我的测试 因此,我想确保我找到(或没有)的Mercurial

我有一个.NET类库,它可以启动一个辅助进程,该进程将一直运行,直到我处理完对象为止

由于程序在内存中出现了一些延迟,我决定添加一个集成测试,以确保如果我让对象进入GC/终结,该过程将停止

但是,由于该进程是Mercurial命令行客户端,并且我的构建服务器已经在运行Mercurial作为其自身操作的一部分,因此我设想的情况是,Mercurial在测试启动时已经运行,或者在测试结束时,它已经启动,并且仍然在运行,与构建服务器相关,而不是我的测试

因此,我想确保我找到(或没有)的Mercurial客户机是我启动的客户机,而不仅仅是当前正在运行的任何客户机

所以问题是:

  • 我如何才能确定我正在查看的Mercurial客户端是否是由我的流程启动的
通过“查看”,我正在使用该方法,但这不是一个要求

如果一个不同的问题更好,“如何找到我自己进程的所有子进程”,即更容易回答,那么这个问题也就足够了


我找到了这个页面:,但似乎我必须给它一个进程名。如果我只给它“hg”,这个问题对于我正在寻找的案例来说不是太模糊了吗?

碰巧我有一点C#/WMI代码,它递归地杀死指定进程id生成的所有进程。杀戮显然不是你想要的,但是发现子进程似乎是你感兴趣的。我希望这会有所帮助:

    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();
                }
            }
        }
    }
虽然这可能是你能得到的最接近的答案,但真正的答案是:你不能

Windows不维护真正的进程树,在该树中,当中间级别的进程死亡时,进程将被重新构造。但是,Windows确实记得父进程ID

有问题的情况如下:

原始流程结构:

YourApp.exe
- SubApp.exe
  - Second.exe
如果现在SubApp.exe终止,则Second.exe的父进程ID将不会更新。新的结果是

YourApp.exe
Second.exe

您可以使用来验证这一点。它能够以树的形式显示流程。启动CMD,然后键入
Start CMD
。在新窗口中,再次键入
start cmd
。您将打开3个窗口。现在终止中间的一个。

谢谢!根据之前的KillAllProcessPawnedBy Answer,我做了以下几点:

        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();

        }

这对我来说效果很好,尽管我使用
ManagementObject
和无搜索器来实现更简单的方法。我一直在努力终止我的子进程有一段时间了,谢谢!需要系统。管理程序集/参考这对我很有用,谢谢``对于那些希望使用我的答案代码的人来说,这篇文章是对其局限性的合理警告,然而最初的问题是关于嵌套在最多1层的父进程和子进程,而不是这里描述的>1层。