I'm using a BackgroundWorker object to start a process, the following is inside of my BackgroundWorker.DoWork event:

...

process.StartInfo.FileName = "process.exe";
process.StartInfo.Arguments = arguments;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.EnableRaisingEvents = true;
process.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
process.Start();
process.BeginOutputReadLine();

while (process.HasExited == false)
{
    if (worker.CancellationPending == true)
    {
        process.Kill();
        process.WaitForExit();
        CleanUpMethod();
        e.Cancel = true;
    }
}

....

The main reason i need to kill the process is to delete temporary files used by the process that cannot be deleted while the process is running.

When debugging i've discovered that process.Kill() doesn't seem to be doing anything. The next line process.WaitForExit() just waits until the process runs its normal procedures.

For my purposes of cleaning up resources, my code seems to work fine. But ideally i want to be able to control the lifetime of the process. Could this have something to do with admin permissions? Any ideas?

Recommended Answers

All 7 Replies

Does the process you are running have a window (or a message pump?). If it does, use .CloseMainWindow() instead of .Kill() . .Kill should terminate the process but I think it requires admin priveleges, whereas I don't think CloseMainWindow() requires it.

There's a distinct difference between the two - Kill() instantly terminates the process and does no cleanup whatsoever (open file handles won't be closed, etc) similar to killing a process in task manager, whereas CloseMainWindow() sends a request to the program's message pump to close. Assuming there is no on_close event handler in the process to prevent it from closing (like in word when it asks you if you want to save) then it should close tidily.

Does the process you are running have a window (or a message pump?). If it does, use .CloseMainWindow() instead of .Kill() . .Kill should terminate the process but I think it requires admin priveleges, whereas I don't think CloseMainWindow() requires it.

There's a distinct difference between the two - Kill() instantly terminates the process and does no cleanup whatsoever (open file handles won't be closed, etc) similar to killing a process in task manager, whereas CloseMainWindow() sends a request to the program's message pump to close. Assuming there is no on_close event handler in the process to prevent it from closing (like in word when it asks you if you want to save) then it should close tidily.

The process does not have a window or any sort of interface. I've already tried using CloseMainWindow() in place of Kill() and i get the same result. The process is not killed.

Try running it as an administrator and let me know what happens.

Try running it as an administrator and let me know what happens.

I figured out what the problem is, but still need a solution.

The process is creating another instance of it self (so there are 2 instances of the process running). When i call process.Kill(), one of them is killed, and one of them is still running, causing process.WaitForExit() to wait.

The only solution i can think of is searching all running processes by name and killing it that way.. which doesn't sound ideal.

The must be another way, especially considering the fact the all instances of the process are killed when my application exits.

You can get all the PID's created by a parent process using windows management objects (using recursion):

private void KillProcessAndChildren(int pid)
{
     ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
     ManagementObjectCollection moc = searcher.Get();
     foreach (ManagementObject mo in moc)
     {    
          KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
     }
     try
     {
         Process proc = Process.GetProcessById(pid);
         proc.Kill();
     }
     catch (ArgumentException)
     { /* process already exited */ }
}

You can get the parent proc id with the process.ID member. Give it a whirl and let me know if it works. This is effectively how 'Kill Process Tree' works in taskmanager

You can get all the PID's created by a parent process using windows management objects (using recursion):

private void KillProcessAndChildren(int pid)
{
     ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
     ManagementObjectCollection moc = searcher.Get();
     foreach (ManagementObject mo in moc)
     {    
          KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
     }
     try
     {
         Process proc = Process.GetProcessById(pid);
         proc.Kill();
     }
     catch (ArgumentException)
     { /* process already exited */ }
}

You can get the parent proc id with the process.ID member. Give it a whirl and let me know if it works. This is effectively how 'Kill Process Tree' works in taskmanager

Worked perfectly. Thanks alot

Dispose?

I had a similar problem with interops and had to force a GC.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.