有没有办法确保我的程序生成的后台进程在我的进程终止时被终止?

Dav*_*vy8 7 c# child-process

基本上,子进程无限期地运行直到在后台被杀死,并且当我的程序因任何原因终止时,我想要清理它,即通过Taskmanager.

目前我有一段时间(Process.GetProcessesByName("ParentProcess").Count()> 0)循环并退出,如果父进程没有运行,但它似乎非常脆弱,如果我希望它在Visual中的调试器下工作Studio我必须添加"ParentProcess.vshost"或其他东西.

有没有办法确保子进程在不要求子进程知道父进程的情况下结束?我更喜欢托管代码中的解决方案,但如果没有,我可以PInvoke.

编辑:传递PID似乎是一个更强大的解决方案,但出于好奇心的缘故,如果子进程不是我的代码而是一些我无法控制的exe怎么办?有没有办法防止可能创建孤立的子进程?

Jon*_*eet 7

如果子进程是您自己的代码,则可以在启动它时将其传递给父进程的PID.然后,子进程可以使用处理程序获取进程Process.GetProcessByIdExited使用处理程序订阅其事件,该处理程序可以正常关闭(子)进程的其余部分.请注意,您需要EnableRaisingEvents将进程的属性设置为true.


Ala*_*sel 5

如果子进程不是您自己的代码,您可以使用此代码查找并终止所有子进程:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Util {
    public static class ProcessExtensions {
        public static void KillDescendants(this Process processToNotKillYet) {
            foreach (var eachProcess in Process.GetProcesses()) {
                if (eachProcess.ParentPid() == processToNotKillYet.Id) {
                    eachProcess.KillTree();
                }
            }
        }

        public static void KillTree(this Process processToKill) {
            processToKill.KillDescendants();
            processToKill.Kill();
        }

        public static PROCESS_BASIC_INFORMATION Info(this Process process) {
            var processInfo = new PROCESS_BASIC_INFORMATION();
            try {
                uint bytesWritten;
                NtQueryInformationProcess(process.Handle,
                                          0,
                                          ref processInfo,
                                          (uint)Marshal.SizeOf(processInfo),
                                          out bytesWritten); // == 0 is OK
            }
            catch (Win32Exception e) {
                if (!e.Message.Equals("Access is denied")) throw;
            }

            return processInfo;
        }

        public static int ParentPid(this Process process) {
            return process.Info().ParentPid;
        }

        [DllImport("ntdll.dll")]
        private static extern int NtQueryInformationProcess(
            IntPtr hProcess,
            int processInformationClass /* 0 */,
            ref PROCESS_BASIC_INFORMATION processBasicInformation,
            uint processInformationLength,
            out uint returnLength);

        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESS_BASIC_INFORMATION {
            public int ExitStatus;
            public int PebBaseAddress;
            public int AffinityMask;
            public int BasePriority;
            public int Pid;
            public int ParentPid;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)