问题 如何在没有“进程退出”异常的情况下杀死进程?


我用 Process.Kill() 杀死一个进程。喜欢这个:

if( !process.WaitForExit( 5000 ) ) {
   process.Kill();
}

有时这个过程会在行之间退出,所以控制权就会进入 if 接着 Kill 将产生一个例外:

System.InvalidOperationException
Cannot process request because the process (ProcessIdHere) has exited.
at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited)
at System.Diagnostics.Process.Kill()
//my code here

现在将代码包装到try-catch中似乎不是一个好主意,因为 InvalidOperationException 可以因其他原因而被召唤。

有没有办法在所描述的场景中杀死进程而不会出现异常?


5537
2017-11-26 12:13


起源

你试过检查内部异常吗?可能会给你一个确切的例外处理。 - Yahya
@Yahya:Yeap,内部异常始终为null。 - sharptooth


答案:


你可以P / Invoke TerminateProcess 通过它 Process.Handle。然后手动评估其原因(GetLastError())。什么是粗略的 Process.Kill() 在内部。

但请注意 TerminateProcess 是异步的。因此,您必须等待进程句柄以确保完成。 运用 Process.Kill() 这样做是为了你的。

更新: 更正, Process.Kill() 也是异步运行的。所以你必须使用 WaitForExit() 等待终止完成 - 如果你在意的话。

坦率地说,我不会打扰。当然总有(遥远的)机会有些“随意” InvalidOperationExcepion 从那行代码中冒出来,这与流程不再存在或与之相关 Process 对象处于无效状态,但实际上我认为你可以随身携带try / catch Kill

此外,根据您的应用程序,您可以考虑记录此杀死,因为它似乎是某种最后的措施。在那种情况下记录实际情况 InvalidOperationException 用它。如果事情变得奇怪,你至少要让你的日志检查为什么 Kill 失败。

尽管如此,您可能还想考虑捕获/处理 Win32Exception 出于同样的原因。


9
2017-11-26 12:23



+1是一个明智的现实世界的方法。 - tomfanning


你需要使用 HasExited

if(!process.WaitForExit(5000)) 
{
   if (!process.HasExited)
   {
       process.Kill();
   }
}

看这里:

http://msdn.microsoft.com/en-us/library/system.diagnostics.process.hasexited.aspx


3
2017-11-26 12:22



那仍然有竞争条件。 HasExited 可能会回来 false,但到时候 Kill 执行,过程可能会消失 - 导致一个 InvalidOperationException 仍然。 - Christian.K
我们谈论的是几分之一秒,所以看起来似乎不太可能,但如果是这种情况你无法阻止它,那么你能做的最好就是捕捉异常。 - Lloyd
说实话,“毫微秒的分数”似乎有点夸张。你的过程可能会被发现,例如,在两次调用之间,哎呀,盒子甚至可能在“不幸的顺序”中重新进入休眠状态;-)但我同意,捕获异常是唯一的“强大”解决方案 - 如果你关心。 YMMV当然。 - Christian.K
好的,我只是意味着这是一个非常小的机会。这是一个小机会,并且应该处理:) - Lloyd