c# - 在 Process 中调用 robocopy 的批处理脚本不会终止

标签 c# .net windows batch-file robocopy

如果从另一个线程甚至另一个程序调用 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.CancelErrorReadprocess.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/

相关文章:

Python3 Windows 多处理传递套接字到进程

c++ - 如何轻松检测字符串中的utf8编码?

windows - 如何在 Windows 上将 Chrome 的 "Copy as cURL"用于多部分/表单数据发布请求?

c# - 如何将选择的存储过程映射到 EF 3.5 中的实体?

c# - OutOfMemoryException 与 gcAllowVeryLargeObjects

c# - 为什么我的系统在写入控制台时会发出蜂鸣声

c# - SelectCommand 属性在调用 'Fill' 之前尚未初始化。在窗体中

c# - 为什么密封类型更快?

c# - DTS 脚本任务 : Runtime Error in SSIS task due to referenced DLLs

c# - 如何将 ContextFlyout 与 ListView 一起使用?