在C#中以编程方式终止Vista/Windows 7中的进程

10

我想在Vista/Windows 7中以编程的方式终止一个进程(我不确定UAC在两者之间的实现是否存在重大问题,会导致差异)。

目前,我的代码如下:

  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);
   }

我之所以要这样做,是因为我需要确保如果用户崩溃了程序或者突然退出了程序,这个辅助进程会在重新启动应用程序时重新启动,或者如果用户想要更改这个辅助进程的参数。

代码在XP上运行良好,但在Windows 7(我认为在Vista中也是如此)出现“访问被拒绝”的错误消息。根据伟大的谷歌所说,我需要以管理员身份运行我的结束程序以解决这个问题,但这只是一个权宜之计。另一个潜在的答案是使用LinkDemand,但我不理解与进程相关的LinkDemand的msdn页面。

我可以将代码移入线程中,但这会带来一系列其他固有的困难,我真的不想去发现。


Kill() 对于由资源管理器和同一应用程序创建的进程都可以正常工作。我在这里使用受限用户运行 Vista,一切正常。 - Simon Buchan
也许只是Windows 7的一个bug?你能在回答中发布你的代码吗?因为这让我感到困惑。 - mmr
2个回答

5

您说得对,这是因为您没有管理员权限。您可以通过在本地系统用户下安装服务并根据需要运行自定义命令来解决此问题。

在您的Windows窗体应用程序中:

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);

为您服务:

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;
    }
}

这是一个解决方案,也很可能是正确的。我需要进一步研究一下;虽然我没有服务方面的经验,但将此过程称为与应用程序并行运行的服务可能是正确的。 - mmr
1
这是我所知道的唯一一种在不让用户遇到烦人的UAC提示的情况下完成此操作的方法。幸运的是,为了实现这一点,您不需要了解有关服务的任何信息(除了安装之外)。我给你添加的带有代码的VS模板将完美地工作。 - Andrew Ensley
是的,这就是正确的方法。感谢您的帮助! - mmr

0

我将添加Simon Buchan建议的代码。假设您的Windows表单是首次启动该进程,它很有道理并且应该同样有效。

这里是您创建进程的位置。请注意变量myProc。那是您对它的控制:

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

之后,只需使用以下命令结束它:

myProc.Kill();

但问题是,应用程序可能意外死亡,或者用户自己强制停止了它。我希望该进程只删除由应用程序的另一个实例启动的其他进程实例。 - mmr
1
那么服务方法可能是您最好(唯一?)的解决方案。 - Andrew Ensley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接