Kill child process when parent process is killed

前端 未结 15 2436
轻奢々
轻奢々 2020-11-22 05:59

I\'m creating new processes using System.Diagnostics.Process class from my application.

I want this processes to be killed when/if my application has cr

相关标签:
15条回答
  • 2020-11-22 06:31

    I've made a child process management library where the parent process and the child process are monitored due a bidirectional WCF pipe. If either the child process terminates or the parent process terminates each other is notified. There is also a debugger helper available which automatically attaches the VS debugger to the started child process

    Project site:

    http://www.crawler-lib.net/child-processes

    NuGet Packages:

    https://www.nuget.org/packages/ChildProcesses https://www.nuget.org/packages/ChildProcesses.VisualStudioDebug/

    0 讨论(0)
  • 2020-11-22 06:31

    Solution that worked for me:

    When creating process add tag process.EnableRaisingEvents = true;:

    csc = new Process();
    csc.StartInfo.UseShellExecute = false;
    csc.StartInfo.CreateNoWindow = true;
    csc.StartInfo.FileName = Path.Combine(HLib.path_dataFolder, "csc.exe");
    csc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    csc.StartInfo.ErrorDialog = false;
    csc.StartInfo.RedirectStandardInput = true;
    csc.StartInfo.RedirectStandardOutput = true;
    csc.EnableRaisingEvents = true;
    csc.Start();
    
    0 讨论(0)
  • 2020-11-22 06:32

    I see two options:

    1. If you know exactly what child process could be started and you are sure they are only started from your main process, then you could consider simply searching for them by name and kill them.
    2. Iterate through all processes and kill every process that has your process as a parent (I guess you need to kill the child processes first). Here is explained how you can get the parent process id.
    0 讨论(0)
  • 2020-11-22 06:34

    There is another relevant method, easy and effective, to finish child processes on program termination. You can implement and attach a debugger to them from the parent; when the parent process ends, child processes will be killed by the OS. It can go both ways attaching a debugger to the parent from the child (note that you can only attach one debugger at a time). You can find more info on the subject here.

    Here you have an utility class that launches a new process and attaches a debugger to it. It has been adapted from this post by Roger Knapp. The only requirement is that both processes need to share the same bitness. You cannot debug a 32bit process from a 64bit process or vice versa.

    public class ProcessRunner
    {
        // see http://csharptest.net/1051/managed-anti-debugging-how-to-prevent-users-from-attaching-a-debugger/
        // see https://stackoverflow.com/a/24012744/2982757
    
        #region "API imports"
    
        private const int DBG_CONTINUE = 0x00010002;
        private const int DBG_EXCEPTION_NOT_HANDLED = unchecked((int) 0x80010001);
    
        private enum DebugEventType : int
        {
            CREATE_PROCESS_DEBUG_EVENT = 3,
            //Reports a create-process debugging event. The value of u.CreateProcessInfo specifies a CREATE_PROCESS_DEBUG_INFO structure.
            CREATE_THREAD_DEBUG_EVENT = 2,
            //Reports a create-thread debugging event. The value of u.CreateThread specifies a CREATE_THREAD_DEBUG_INFO structure.
            EXCEPTION_DEBUG_EVENT = 1,
            //Reports an exception debugging event. The value of u.Exception specifies an EXCEPTION_DEBUG_INFO structure.
            EXIT_PROCESS_DEBUG_EVENT = 5,
            //Reports an exit-process debugging event. The value of u.ExitProcess specifies an EXIT_PROCESS_DEBUG_INFO structure.
            EXIT_THREAD_DEBUG_EVENT = 4,
            //Reports an exit-thread debugging event. The value of u.ExitThread specifies an EXIT_THREAD_DEBUG_INFO structure.
            LOAD_DLL_DEBUG_EVENT = 6,
            //Reports a load-dynamic-link-library (DLL) debugging event. The value of u.LoadDll specifies a LOAD_DLL_DEBUG_INFO structure.
            OUTPUT_DEBUG_STRING_EVENT = 8,
            //Reports an output-debugging-string debugging event. The value of u.DebugString specifies an OUTPUT_DEBUG_STRING_INFO structure.
            RIP_EVENT = 9,
            //Reports a RIP-debugging event (system debugging error). The value of u.RipInfo specifies a RIP_INFO structure.
            UNLOAD_DLL_DEBUG_EVENT = 7,
            //Reports an unload-DLL debugging event. The value of u.UnloadDll specifies an UNLOAD_DLL_DEBUG_INFO structure.
        }
    
        [StructLayout(LayoutKind.Sequential)]
        private struct DEBUG_EVENT
        {
            [MarshalAs(UnmanagedType.I4)] public DebugEventType dwDebugEventCode;
            public int dwProcessId;
            public int dwThreadId;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] public byte[] bytes;
        }
    
        [DllImport("Kernel32.dll", SetLastError = true)]
        private static extern bool DebugActiveProcess(int dwProcessId);
    
        [DllImport("Kernel32.dll", SetLastError = true)]
        private static extern bool WaitForDebugEvent([Out] out DEBUG_EVENT lpDebugEvent, int dwMilliseconds);
    
        [DllImport("Kernel32.dll", SetLastError = true)]
        private static extern bool ContinueDebugEvent(int dwProcessId, int dwThreadId, int dwContinueStatus);
    
        [DllImport("Kernel32.dll", SetLastError = true)]
        public static extern bool IsDebuggerPresent();
    
        #endregion
    
        public Process ChildProcess { get; set; }
    
        public bool StartProcess(string fileName)
        {
            var processStartInfo = new ProcessStartInfo(fileName)
            {
                UseShellExecute = false,
                WindowStyle = ProcessWindowStyle.Normal,
                ErrorDialog = false
            };
    
            this.ChildProcess = Process.Start(processStartInfo);
            if (ChildProcess == null)
                return false;
    
            new Thread(NullDebugger) {IsBackground = true}.Start(ChildProcess.Id);
            return true;
        }
    
        private void NullDebugger(object arg)
        {
            // Attach to the process we provided the thread as an argument
            if (DebugActiveProcess((int) arg))
            {
                var debugEvent = new DEBUG_EVENT {bytes = new byte[1024]};
                while (!this.ChildProcess.HasExited)
                {
                    if (WaitForDebugEvent(out debugEvent, 1000))
                    {
                        // return DBG_CONTINUE for all events but the exception type
                        var continueFlag = DBG_CONTINUE;
                        if (debugEvent.dwDebugEventCode == DebugEventType.EXCEPTION_DEBUG_EVENT)
                            continueFlag = DBG_EXCEPTION_NOT_HANDLED;
                        ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, continueFlag);
                    }
                }
            }
            else
            {
                //we were not able to attach the debugger
                //do the processes have the same bitness?
                //throw ApplicationException("Unable to attach debugger") // Kill child? // Send Event? // Ignore?
            }
        }
    }
    

    Usage:

        new ProcessRunner().StartProcess("c:\\Windows\\system32\\calc.exe");
    
    0 讨论(0)
  • 2020-11-22 06:36

    call job.AddProcess better to do after start of the process:

    prc.Start();
    job.AddProcess(prc.Handle);
    

    When calling AddProcess before the terminate, child processes are not killed. (Windows 7 SP1)

    private void KillProcess(Process proc)
    {
        var job = new Job();
        job.AddProcess(proc.Handle);
        job.Close();
    }
    
    0 讨论(0)
  • 2020-11-22 06:40

    Use event handlers to make hooks on a few exit scenarios:

    var process = Process.Start("program.exe");
    AppDomain.CurrentDomain.DomainUnload += (s, e) => { process.Kill(); process.WaitForExit(); };
    AppDomain.CurrentDomain.ProcessExit += (s, e) => { process.Kill(); process.WaitForExit(); };
    AppDomain.CurrentDomain.UnhandledException += (s, e) => { process.Kill(); process.WaitForExit(); };
    
    0 讨论(0)
提交回复
热议问题