I needed the ability to kill a process and any of its child processes, but System.Process.Kill() does not kill any child processes.
I tried using the JobObjectWrapper library, but unfortunately it doesn't work when running from an existing job, which is exactly the scenario I needed since Visual Studio 2005 on Windows Vista is already running under a job.
The solution I opted for was to use the WindowsXP Pro/Windows Vista taskkill.exe utility since it supports kill a task tree.
/// <summary>
/// Will kill a process and all its child processes. This class requires
/// taskkill.exe present in the WINDIR\System32 directory.
/// </summary>
public class TaskKill
{
private readonly int pid;
private readonly string imageName;
public TaskKill(string imageName)
{
this.imageName = imageName;
}
public TaskKill(int pid)
{
this.pid = pid;
}
/// <summary>
/// Kills the process associated with this TaskKill instance.
/// </summary>
public void KillAssociatedProcess()
{
if (!string.IsNullOrEmpty(imageName))
KillProcessByName();
else
KillProcessById();
}
protected void KillProcessById()
{
string killArgs = string.Format("/F /PID {0} /T", pid);
ExecuteKill(killArgs);
}
protected void KillProcessByName()
{
string killArgs = string.Format("/F /IM {0} /T", imageName);
ExecuteKill(killArgs);
}
protected string GetTaskKillExePath()
{
string taskKillPath = Path.Combine(Environment.SystemDirectory, "taskkill.exe");
if (!File.Exists(taskKillPath))
throw new FileNotFoundException(
"Cannot find taskkill.exe in the Windows Sytem32 directory. Are you running WindowsXP Home which doesn't include this utility?");
return taskKillPath;
}
private void ExecuteKill(string processShellArgs)
{
ProcessStartInfo info = new ProcessStartInfo(GetTaskKillExePath(), processShellArgs);
info.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = info;
process.Start();
process.WaitForExit(5000);
}
}
The code that uses the TaskKill class looks like this:
[Test]
public void Test1()
{
ProcessStartInfo info = new ProcessStartInfo("notepad.exe");
Process process = new Process();
process.StartInfo = info;
process.Start();
Assert.That(!process.HasExited, "Process exited early");
TaskKill taskKill = new TaskKill(process.Id);
taskKill.KillAssociatedProcess();
Assert.That(process.HasExited, "TaskKill failed to kill the process");
}