Пример #1
0
        private void WindowsKillProcessTree()
        {
            var pid = _proc?.Id;

            if (pid == null)
            {
                // process already exit, stop here.
                return;
            }

            Dictionary <int, int> processRelationship = new Dictionary <int, int>();

            //Trace.Info($"Scan all processes to find relationship between all processes.");

            foreach (Process proc in Process.GetProcesses())
            {
                try
                {
                    if (!proc.SafeHandle.IsInvalid)
                    {
                        ProccessData pbi          = new ProccessData();
                        int          returnLength = 0;
                        int          queryResult  = NtQueryInformationProcess(proc.SafeHandle.DangerousGetHandle(), PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), ref returnLength);
                        if (queryResult == 0) // == 0 is OK
                        {
                            //Trace.Verbose($"Process: {proc.Id} is child process of {pbi.InheritedFromUniqueProcessId}.");

                            processRelationship[proc.Id] = (int)pbi.InheritedFromUniqueProcessId;
                        }
                        else
                        {
                            throw new Win32Exception(Marshal.GetLastWin32Error());
                        }
                    }
                }
                catch (Exception ex)
                {
                    // Ignore all exceptions, since KillProcessTree is best effort.
                    //Trace.Verbose("Ignore any catched exception during detecting process relationship.");
                    //Trace.Verbose(ex.ToString());
                }
            }

            //Trace.Verbose($"Start killing process tree of process '{pid.Value}'.");

            Stack <ProcessTermination> processesNeedtoKill = new Stack <ProcessTermination>();

            processesNeedtoKill.Push(new ProcessTermination(pid.Value, false));
            while (processesNeedtoKill.Count() > 0)
            {
                ProcessTermination procInfo          = processesNeedtoKill.Pop();
                List <int>         childProcessesIds = new List <int>();
                if (!procInfo.ChildPidExpanded)
                {
                    //Trace.Info($"Find all child processes of process '{procInfo.Pid}'.");
                    childProcessesIds = processRelationship.Where(p => p.Value == procInfo.Pid).Select(k => k.Key).ToList();
                }

                if (childProcessesIds.Count > 0)
                {
                    //Trace.Info($"Need kill all child processes trees before kill process '{procInfo.Pid}'.");
                    processesNeedtoKill.Push(new ProcessTermination(procInfo.Pid, true));
                    foreach (var childPid in childProcessesIds)
                    {
                        //Trace.Info($"Child process '{childPid}' needs be killed first.");
                        processesNeedtoKill.Push(new ProcessTermination(childPid, false));
                    }
                }
                else
                {
                    //Trace.Info($"Kill process '{procInfo.Pid}'.");

                    try
                    {
                        Process leafProcess = Process.GetProcessById(procInfo.Pid);
                        try
                        {
                            leafProcess.Kill();
                        }
                        catch (InvalidOperationException ex)
                        {
                            // The process has already exited
                            //Trace.Verbose("Ignore InvalidOperationException during Process.Kill().");
                            //Trace.Verbose(ex.ToString());
                        }
                        catch (Win32Exception ex) when(ex.NativeErrorCode == 5)
                        {
                            // The associated process could not be terminated
                            // The process is terminating
                            // NativeErrorCode 5 means Access Denied
                            //Trace.Verbose("Ignore Win32Exception with NativeErrorCode 5 during Process.Kill().");
                            //Trace.Verbose(ex.ToString());
                        }
                        catch (Exception ex)
                        {
                            // Ignore any additional exception
                            //Trace.Verbose("Ignore additional exceptions during Process.Kill().");
                            //Trace.Verbose(ex.ToString());
                        }
                    }
                    catch (ArgumentException ex)
                    {
                        // process already gone, nothing needs killed.
                        //Trace.Verbose("Ignore ArgumentException during Process.GetProcessById().");
                        //Trace.Verbose(ex.ToString());
                    }
                    catch (Exception ex)
                    {
                        // Ignore any additional exception
                        //Trace.Verbose("Ignore additional exceptions during Process.GetProcessById().");
                        //Trace.Verbose(ex.ToString());
                    }
                }
            }
        }
Пример #2
0
 private static extern int NtQueryInformationProcess(IntPtr processHandle, PROCESSINFOCLASS processInformationClass, ref ProccessData processInformation, int processInformationLength, ref int returnLength);