来自C#的命令提示被卡住了

时间:2016-02-20 16:19:26

标签: c# cmd

前几天我问过this question,但我既没有答案,也没有让它成功。因此,我试图将其缩小,因为问题中存在很多噪音。

事情是,如果我在web api中公开了一个运行cmd.exe的方法,那么如果我不按每次请求调用它两次就可以正常工作。

我的意思是,这段代码运行良好:

data[0] -> PPG
data[1] -> bonds (AMT, current US$)

但是,如果我取消注释评论的行(显然注释掉public class FilesController : ApiController { private readonly IRunner _runner; public FilesController(IRunner runner) { _runner = runner; } public string Get() { return _runner.GetFiles(); } } public class Runner : IRunner { public Runner() { //var cd = @"cd C:\DummyFolder"; //RunCmdPromptCommand(cd); } public string GetFiles() { var dir = @"cd C:\DummyFolder & dir"; //var dir = "dir"; return RunCmdPromptCommand(dir); } private string RunCmdPromptCommand(string command) { var process = new Process { StartInfo = { UseShellExecute = false, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardError = true, RedirectStandardOutput = true, FileName = @"cmd.exe", Arguments = string.Format("/C {0}", command) } }; process.Start(); var error = process.StandardError.ReadToEnd(); if (!string.IsNullOrEmpty(error)) { throw new Exception(error); } var output = process.StandardOutput.ReadToEnd(); process.WaitForExit(); return output; } } 的第一行,当代码第二次到达时(即使用“dir”)GetFiles它会卡在它尝试读取标准错误的行。

我不知道为什么,而且我不知道如何在可能发生的情况下强制退出(可能是其他可能发生的情况)

谢谢,

1 个答案:

答案 0 :(得分:5)

这是因为:

process.StandardOutput.ReadToEnd();

是同步操作。

摘自MSDN

  

可以同步读取重定向的StandardError流   异步。执行Read,ReadLine和 ReadToEnd 等方法   对进程的错误输出流执行同步读取操作。   这些同步读取操作在关联之前不会完成   进程写入其StandardError流,或关闭流

换句话说,只要进程没有写任何标准错误或关闭流,它就会永远卡在那里。

要解决此问题,建议您使用Async BeginErrorReadLine。摘自MSDN:

  

相反, BeginErrorReadLine 启动异步读取操作   StandardError流。此方法启用指定事件   流输出的处理程序并立即返回给调用者,   可以在将流输出定向到事件处理程序时执行其他工作。

我认为这将适合您的需要。

使用它。 MSDN中给出的示例非常简单。特别查看这些内容:

 netProcess.ErrorDataReceived += new DataReceivedEventHandler(NetErrorDataHandler); //note this event handler add

if (errorRedirect) //in your case, it is not needed
{
    // Start the asynchronous read of the standard
    // error stream.
    netProcess.BeginErrorReadLine(); //note this
}

以及如何定义事件处理程序:

private static void NetErrorDataHandler(object sendingProcess, 
    DataReceivedEventArgs errLine)
{
    // Write the error text to the file if there is something
    // to write and an error file has been specified.

    if (!String.IsNullOrEmpty(errLine.Data))
    {
        if (!errorsWritten)
        {
            if (streamError == null)
            {
                // Open the file.
                try 
                {
                    streamError = new StreamWriter(netErrorFile, true);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Could not open error file!");
                    Console.WriteLine(e.Message.ToString());
                }
            }

            if (streamError != null)
            {
                // Write a header to the file if this is the first
                // call to the error output handler.
                streamError.WriteLine();
                streamError.WriteLine(DateTime.Now.ToString());
                streamError.WriteLine("Net View error output:");
            }
            errorsWritten = true;
        }

        if (streamError != null)
        {
            // Write redirected errors to the file.
            streamError.WriteLine(errLine.Data);
            streamError.Flush();
        }
    }
}