如果从另一个线程甚至另一个程序调用 process.Kill()
,如果批处理脚本使用 robocopy.exe,则进程永远不会从 WaitForExit()
中退出直到它像没有被杀死一样完成。
Robocopy.exe 从批处理脚本中调用。所有其他脚本或程序都按您的预期结束。
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "batch.bat";
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
startInfo.OutputDataReceived += CaptureHandler;
startInfo.RedirectStandardError = true;
startInfo.ErrorDataReceived += CaptureHandler;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
批处理脚本如下所示:
@echo off
call "robocopy.exe" "somedir" "somedest" /mir /fp /ndl /njh /njs /ns
我觉得它与输出处理程序有关。
我尝试在 Kill()
调用之后和之前使用 process.CancelErrorRead
和 process.CancelOutputRead()
,但没有成功。
奇怪的是,如果您使用 process.WaitForExit(timeout)
重载,它将在来自另一个线程的 Kill()
之后立即返回 true。然而,这是在说谎。进程还在运行!如果您再次尝试 process.WaitForExit()
,根据 MSDN 文档,它仍将等待进程完成,尽管 HasExited
为 true。
To ensure that asynchronous event handling has been completed, call the WaitForExit() overload that takes no parameter after receiving a true from this overload.
https://msdn.microsoft.com/en-us/library/ty0d8k56(v=vs.110).aspx
最佳答案
您已成功终止批处理程序 (cmd.exe),但这样做不会终止 robocopy,这是一个单独的进程。
它doesn't seem to be documented,但是when we look at the .NET source code事实证明,Process.WaitForExit()
方法不只是等待进程退出,它还等待结束- 标准输出和标准错误流上的文件。在这种情况下,这意味着它会等待 robocopy 完成,即使在批处理器已被终止后也是如此。
(带有超时的 Process.WaitForExit
的重载没有这个额外的逻辑。)
我认为这构成了 .NET 框架中的错误。至少,它应该被记录下来。
作为解决方法,您可以使用 .HasExited
和/或带有超时的 WaitForExit
版本来确定进程是否已退出。当然,在您的场景中,您可能更愿意等待孙子进程,在这种情况下您的代码已经按预期运行。
关于c# - 在 Process 中调用 robocopy 的批处理脚本不会终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44712364/