无法从cmd获取输出

本文关键字:获取 输出 cmd | 更新日期: 2023-09-27 17:49:48

我正在运行这个

        string path = string.Format(@"''{0}'c$'Windows'CCM'Logs", computerName);
        Process process = Process.Start(new ProcessStartInfo()
        {
            FileName = "cmd.exe",
            Arguments = string.Format(@"net use {0} && dir {0}", path),
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true
        });
        string result = process.StandardOutput.ReadToEnd() + " " + process.StandardError.ReadToEnd();
        process.WaitForExit();
        Console.WriteLine(result);

但是没有向控制台写入任何内容。我做错了什么?我可能已经浏览了关于这个的每一个其他SO线程,并做了相当数量的谷歌搜索,但我不能让它工作。

无法从cmd获取输出

您需要使用/C选项来cmd.exe,否则子进程将无法退出。

/C执行string指定的命令,然后终止

(在命令提示符中输入cmd /?以获取更多信息)

RedirectStandardOutput = true;RedirectStandardError = true;将重定向各自的流。要捕获这些流,您需要按如下方式处理OutputDataReceived事件:

process.EnableRaisingEvents = true;
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.BeginOutputReadLine();

我使用以下代码将进程的StandardError和StandardOutput打印到Debug/Console

using (StreamReader reader = process.StandardError) {
  string result = reader.ReadToEnd();
  System.Diagnostics.Debug.Write(result);
}
using (StreamReader reader = process.StandardOutput) {
  string result = reader.ReadToEnd();
  System.Diagnostics.Debug.Write(result);
}
process.WaitForExit();

我还在StartInfo

上设置了以下属性
StartInfo.UseShellExecute = false;
StartInfo.ErrorDialog = false;
StartInfo.RedirectStandardOutput = true;
StartInfo.RedirectStandardError = true;

我认为您正面临文档中所描述的死锁:

如果父进程调用p.s ardoutput . readtoend和p.s arderror . readtoend,并且子进程写入足够的文本来填充其错误流,则会导致死锁条件。父进程将无限期地等待子进程关闭其StandardOutput流。子进程将无限期地等待父进程从完整的标准错误流中读取。

为了避免这种情况,你应该在其中一个流上使用异步读操作:

p.BeginOutputReadLine();
string error = p.StandardError.ReadToEnd();
p.WaitForExit();

请查看MSDN文档

我知道这是旧的,但我想分享我的解决方案,当我遇到这个线程。没有适合我需要的答案。我不想在进程结束时读取输出。这就是我想出来的解决方案。该解决方案可同时解决快速和慢速响应,因此将始终获得所有输出。

...
process = Process.Start(processInfo);
process.ErrorDataReceived += (sender, eargs) =>
{
    // do something
};
process.OutputDataReceived += (sender, eargs) =>
{
    // do something
};
if (timeout > 0)
{
    // if it is a slow process, read async
    if (!process.WaitForExit(200))
    {
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();
        if (!process.WaitForExit(timeout))
        {
            // show error
            return;
        }
    } else
    {
        // if it is fast process, need to use "ReadToEnd", because async read will not 
        // caputure output
        var text = process.StandardOutput.ReadToEnd();
        // do something with text
    }
    exitCode = process.ExitCode;
}