Search code examples
c#.netprocesskill

Process.Kill() doesn't seem to kill the process


I am having trouble using Process.Kill(). I think I must be misunderstanding how it works. This is my test function. I start a long-running process (ping -t) and then kill it five seconds later.

I can see the ping process show up, but the process is still there after my program finishes. I have to kill it manually.

Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);

ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe");
Process process = new Process();

startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.Arguments = "/c ping -t 8.8.8.8";

Console.WriteLine("Staring ping process");
process.StartInfo = startInfo;
process.Start();
Thread.Sleep(5000);

Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);
Thread.Sleep(5000);

Console.WriteLine("Killing ping process");
process.Kill();
Thread.Sleep(5000);

Console.WriteLine("Total number of ping processes is {0}", Process.GetProcessesByName("ping").Length);

What am I doing wrong here?


Solution

  • You started cmd.exe, then cmd.exe starts child process ping.exe. To kill ping.exe you can kill all process hierarchy. For example with WMI(add System.Management reference):

    private static void KillProcessAndChildrens(int pid)
    {
        ManagementObjectSearcher processSearcher = new ManagementObjectSearcher
          ("Select * From Win32_Process Where ParentProcessID=" + pid);
        ManagementObjectCollection processCollection = processSearcher.Get();
    
        try
        {
            Process proc = Process.GetProcessById(pid);
            if (!proc.HasExited) proc.Kill();
        }
        catch (ArgumentException)
        {
            // Process already exited.
        }
    
        if (processCollection != null)
        {
            foreach (ManagementObject mo in processCollection)
            {
                KillProcessAndChildrens(Convert.ToInt32(mo["ProcessID"])); //kill child processes(also kills childrens of childrens etc.)
            }
        }
    }