views:

4047

answers:

2

Hi all,

I want to kill a process programmatically in vista/windows 7 (I'm not sure if there's significant problems in the implementation of the UAC between the two to make a difference).

Right now, my code looks like:

  if(killProcess){
      System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("MyProcessName");
       // Before starting the new process make sure no other MyProcessName is running.
        foreach (System.Diagnostics.Process p in process)
        {
            p.Kill();
        }

        myProcess = System.Diagnostics.Process.Start(psi);
   }

I have to do this because I need to make sure that if the user crashes the program or exits abruptly, this secondary process is restarted when the application is restarted, or if the user wants to change the parameters for this secondary process.

The code works fine in XP, but fails in Windows 7 (and I assume in Vista) with an 'access is denied' message. From what the Almighty Google has told me, I need to run my killing program as administrator to get around this problem, but that's just weak sauce. The other potential answer is to use LinkDemand, but I don't understand the msdn page for LinkDemand as it pertains to processes.

I could move the code into a thread, but that has a whole host of other difficulties inherent to it that I really don't want to discover.

+1  A: 

You are correct in that it's because you don't have administrative priveleges. You can solve this by installing a service under the local system user and running a custom command against it as needed.

In your windows form app:

private enum SimpleServiceCustomCommands { KillProcess = 128 };

ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control, Environment.MachineName, "SERVICE_NAME");
scp.Assert();
System.ServiceProcess.ServiceController serviceCon = new System.ServiceProcess.ServiceController("SERVICE_NAME", Environment.MachineName);
serviceCon.ExecuteCommand((int)SimpleServiceCustomCommands.KillProcess);

myProcess = System.Diagnostics.Process.Start(psi);

In your service:

private enum SimpleServiceCustomCommands { KillProcess = 128 };

protected override void OnCustomCommand(int command)
{
    switch (command)
    {
        case (int)SimpleServiceCustomCommands.KillProcess:
            if(killProcess)
            {
                System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("MyProcessName");
                // Before starting the new process make sure no other MyProcessName is running.
                foreach (System.Diagnostics.Process p in process)
                {
                    p.Kill();
                }
            }
            break;
        default:
            break;
    }
}
Andrew
This is a solution, and probably the right one. I'll have to look into it; I have no experience with services, though it's probably correct to refer to this process as a service that runs alongside the app.
mmr
It's the only way I know of to accomplish this without the user getting annoying UAC prompt. Fortunately, you shouldn't have to know anything about services (other than the installation thereof) in order to implement this. The VS template with the code I gave you added will work perfectly.
Andrew
Yeah, this is the way to go. Thanks for the help!
mmr
A: 

I'll add the code for Simon Buchan's suggestion. It makes sense and should work as well, assuming your windows form is what launched the process in the first place.

Here's where you create the process. Notice the variable myProc. That's your handle on it:

System.Diagnostics.Process myProc = new System.Diagnostics.Process();
myProc.EnableRaisingEvents=false;
myProc.StartInfo.FileName="PATH_TO_EXE";
myProc.Start();

Later, just kill it with:

myProc.Kill();
Andrew
but the problem is, the app might have died unexpectedly, or the user was aggressive with the killing themselves. I want the process to just remove other instances of the process started by another instance of the app.
mmr
Then the service approach is probably your best (only?) solution.
Andrew