【问题标题】:Process standard output in C# returning empty string在 C# 中处理标准输出返回空字符串
【发布时间】:2013-09-23 10:11:57
【问题描述】:

我正在尝试列出 dumpcap.exe 可以捕获数据的受支持接口。

我要运行的命令是“dumpcap.exe -D”

在我的系统上,它的输出为:-

1. \Device\NPF_{1B627AA8-2A1D-4C90-B560-517CF71B33A5} (Intel(R) 825
Network Connection)
2. \Device\NPF_{7ECC4D31-DF17-49AB-960D-628D0580F3C6} (Microsoft)

我正在尝试通过从 WPF C# 应用程序运行相同的命令来读取上述输出。我有以下代码:-

        Process proc = new Process();

        //set the path to dumpcap.exe (verified by me)
        proc.StartInfo.FileName = "..\\..\\..\\..\\..\\Dumpcap\\dumpcap.exe";

        StringBuilder dumpcapArgs = new StringBuilder();

        dumpcapArgs.Append("-D");

        proc.StartInfo.Arguments = dumpcapArgs.ToString();
        proc.StartInfo.CreateNoWindow = true;
        proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        proc.StartInfo.RedirectStandardOutput = true;
        proc.StartInfo.UseShellExecute = false;

        proc.Start();

        while (!proc.StandardOutput.EndOfStream)
        {
            string line = proc.StandardOutput.ReadLine();
            MessageBox.Show(line);

        }

当我调试时,执行根本不会进入我的 while 循环。 StandardOutput 已经在流的末尾。进一步挖掘 StandardOutput 基流类成员,我看到很多 System.NotSupportedExceptions 在长度、位置等方面。

上面的代码可能有什么问题?

快速观察

我使用以下代码尝试了另一个示例 C# 控制台应用程序:

        Process proc = new Process();

        proc.StartInfo.FileName = "C:\\Karan\\Dumpcap\\dumpcap.exe";
        proc.StartInfo.Arguments = "-D";
        proc.StartInfo.UseShellExecute = false;
        proc.StartInfo.RedirectStandardOutput = true;
        proc.Start();

        Console.WriteLine(proc.StandardOutput.ReadToEnd());

        proc.WaitForExit();

这会按预期打印输出!

但是,如果我尝试读取字符串变量中的标准输出,我会得到一个空字符串。

例如,这会返回一个空字符串:-

       Process proc = new Process();

        proc.StartInfo.FileName = "C:\\Karan\\Dumpcap\\dumpcap.exe";
        proc.StartInfo.Arguments = "-D";
        proc.StartInfo.UseShellExecute = false;
        proc.StartInfo.RedirectStandardOutput = true;
        proc.Start();


        String output = proc.StandardOutput.ReadToEnd();


        proc.WaitForExit();

【问题讨论】:

    标签: c# process


    【解决方案1】:

    你永远不会开始这个过程。你应该这样做使用proc.Start();

    不支持LengthPositionStream 的类似成员,因为代表控制台应用程序的标准的流的长度未知且仅向前流。所以这是正常的,而不是您的代码中的错误。

    【讨论】:

    • 抱歉,我在从 Visual Studio 复制代码时错过了这一行。我的错。已更新。
    【解决方案2】:

    您是否将EnableRaisingEvents 设置为true

    我不确定这是否能解决问题,因为我通常以不同的方式重定向输出:

    private Process proc;
    private string procOutput = string.Empty;
    
    private void StartProc()
    {
        this.procOutput = string.Empty;
        this.proc = new Process();
       ...
        this.proc.StartInfo.UseShellExecute = false;
        this.proc.StartInfo.CreateNoWindow = true;
        this.proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    
        this.proc.EnableRaisingEvents = true;
        this.proc.OutputDataReceived += this.ProcOutputDataReceivedHandler;
        this.proc.Exited += this.ProcExitedHandler;
    
        this.proc.Start();
    
        this.proc.BeginOutputReadLine();
    }
    
    private void ProcOutputDataReceivedHandler(object sendingProcess, DataReceivedEventArgs e)
    {
        if (!string.IsNullOrEmpty(e.Data))
        {
             this.procOutput += e.Data;
        }
    }
    
    private void ProcExitedHandler(object sender, EventArgs e)
    {
        // Check the exitcode for possible errors happened during execution.
        MessageBox.Show(this.procOutput);
    }
    

    【讨论】:

    • 我试过你的方法。我无法在字符串变量中获取输出(它始终为空),但使用标准同步方法(readToEnd() 并使用 Console.WriteLine())打印预期的输出。
    • 这很奇怪。你能在ProcOutputDataReceivedHandler 中设置一个断点来检查它是否真的命中,如果是,e.Data 的内容是什么?
    • 它没有命中 ProcOutputDataReceivedHandler。 BeginOutputReadLine()之后,我的main方法照常存在。
    • 您使用的是控制台应用还是 winforms 应用?如果是控制台应用程序,请尝试在 Main 方法的末尾添加Console.ReadLine(),以确保在您的应用程序完成之前进程已经完成。这里有点试验和错误,因为我无法重现您的问题......
    • 问题中发布的初始代码是一个 WPF C# 应用程序。我快速观察中发布的代码是一个控制台应用程序。
    【解决方案3】:

    试试这个:

    string output = proc.StandardOutput.ReadToEnd();
    proc.WaitForExit();
    
    foreach(var line in output.Split('\r'))
    {
        MessageBox.Show(line);
    }
    

    为什么会这样?当您第一次查询 EndOfStream 时,输出流中可能没有任何内容。这是一个竞争条件。

    我在发布之前查阅了这篇文章。读一读http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput.aspx

    【讨论】:

    • 我在消息框中仍然收到一个空字符串“”。
    • 我认为你非常接近我的问题。我无法在字符串变量中获取输出(它始终为空),但使用标准同步方法(readToEnd() 并使用 Console.WriteLine())打印预期的输出。我认为这与等待进程退出并填充 Console.Writeline() 的缓冲区有关。
    • 我并没有完全那样做,但是根据您关于“它与时间有关”的提示,我添加了另一行,该行也将 StandardError 读入不同的字符串。只是这样做了,所以我现在按预期获得了 StandardOutput 字符串。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    相关资源
    最近更新 更多