在Process中调用robocopy的批处理脚本不会终止 [英] Batch script calling robocopy in Process won't terminate

查看:56
本文介绍了在Process中调用robocopy的批处理脚本不会终止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果从另一个线程甚至另一个程序调用了 process.Kill(),则如果批处理脚本使用了robocopy.exe,则该进程永远不会从 WaitForExit()中出来.直到完成为止,好像它没有被杀死.

If process.Kill() is called from another thread or even another program, the process never comes out of WaitForExit() if the batch script used robocopy.exe until it is finished as if it wasn't killed.

Robocopy.exe从批处理脚本中调用.其他所有脚本或程序均按预期结束.

Robocopy.exe is called from the batch script. Every other script or program ends as you'd expect.

    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().

I have a feeling it has to do with the output handlers. I tried using process.CancelErrorRead and process.CancelOutputRead() as well after the Kill() call and before, no luck.

奇怪的是,如果您使用 process.WaitForExit(timeout)重载,则它将在另一个线程的 Kill()之后立即返回true.但是,它在说谎.该进程仍在运行!如果您再次尝试 process.WaitForExit(),则按照MSDN文档,尽管 HasExited 表示正确,它仍将等待该过程完成.

Oddly, if you use process.WaitForExit(timeout) overload, it will return true immediately after Kill() from the other thread. However, it's lying. The process is still running! If you try process.WaitForExit() again, as per the MSDN doc, it will still wait for the process to finish despite HasExited saying true.

要确保已完成异步事件处理,请在从此重载接收到真值后,调用不带任何参数的WaitForExit()重载.

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,这是一个独立的过程.

You are successfully killing the batch processor (cmd.exe) but doing so won't kill robocopy, which is a separate process.

似乎没有记录在案,,但

It doesn't seem to be documented, but when we look at the .NET source code it turns out that the Process.WaitForExit() method doesn't just wait for the process to exit, it also waits for end-of-file on the standard output and standard error streams. In this scenario, that means that it waits for robocopy to finish even after the batch processor has been killed.

( Process.WaitForExit 的重载带有超时没有这种额外的逻辑.)

(The overload of Process.WaitForExit with a timeout does not have this extra logic.)

我认为这构成了.NET框架中的错误.至少应该将其记录下来.

I think this constitutes a bug in the .NET framework. At the very least, it should be documented.

作为一种解决方法,您可以使用 .HasExited 和/或 WaitForExit 的版本(具有超时)来确定进程是否已退出.当然,在您的情况下,您可能首选等待孙子进程,在这种情况下,您的代码已经表现出期望的状态.

As a workaround, you can use .HasExited and/or the version of WaitForExit with a timeout to determine whether the process has exited or not. Of course, in your scenario you might prefer to wait for grandchild processes, in which case your code is already behaving as desired.

这篇关于在Process中调用robocopy的批处理脚本不会终止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆