c# - C# 的命令提示符卡住了

标签 c# cmd

我问过this question前几天,但我既没有答案,也无法使其发挥作用。所以我试图精简它,因为问题中有很多噪音。

事情是,如果我在 Web api 中将所有内容公开给运行 cmd.exe 的方法,那么如果每个请求不调用它两次,它就可以正常工作。

我的意思是,这段代码工作正常:

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;
    }
}

但是如果我取消注释行注释(并且显然注释掉 GetFiles 的第一行,当代码第二次到达时(即使用“dir”)RunCmdPromptCommand code> 它卡在尝试读取标准错误的行中。

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

谢谢

最佳答案

这是因为:

process.StandardOutput.ReadToEnd();

是同步操作。

摘自MSDN :

The redirected StandardError stream can be read synchronously or asynchronously. Methods such as Read, ReadLine, and ReadToEnd perform synchronous read operations on the error output stream of the process. These synchronous read operations do not complete until the associated Process writes to its StandardError stream, or closes the stream.

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

要解决此问题,我建议使用异步 BeginErrorReadLine 。摘自MSDN:

In contrast, BeginErrorReadLine starts asynchronous read operations on the StandardError stream. This method enables a designated event handler for the stream output and immediately returns to the caller, which can perform other work while the stream output is directed to the event handler.

我认为这会适合您的需求。

使用它。 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();
        }
    }
}

关于c# - C# 的命令提示符卡住了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35525763/

相关文章:

c# - 从命令行运行带有参数的exe

c# - 根据数据类型在 MVC 3 中自动生成 HTML 属性

c# - 在 C# 中查找鼠标的速度

windows - 使用 *.bat CMD 行创建 *.reg 文件

c# - 值不能为空。参数名称 : key (only happens on XAML Designer's design view)

c# - 如何将 Assembly.CodeBase 转换为 C# 中的文件系统路径?

windows - 在cmd中使用dir获取没有路径的文件夹名称

c++ - 无法在 C++ 中使用 system() 更改目录

windows - WMIC命令批量输出非UTF-8文本文件

windows - "%~dp0"和 ".\"之间的区别?