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()); } } } }
private static extern int NtQueryInformationProcess(IntPtr processHandle, PROCESSINFOCLASS processInformationClass, ref ProccessData processInformation, int processInformationLength, ref int returnLength);