异步 C# StartInfo 进程转储 stdout 行,仅当 stderr 未重定向时?

问题描述 投票:0回答:1

我正在开发一个 C# 应用程序,其中运行一个进程,并且输出行按照 c# run CL exe 或批处理 cpture 输出实时输出到文本框? 实时(异步)输出,代码如下这个:

    Process new_process = new Process();

    new_process.StartInfo.FileName = tool_exe;
    new_process.StartInfo.Arguments = tool_arguments;
    new_process.StartInfo.RedirectStandardInput = true;
    new_process.StartInfo.RedirectStandardOutput = true;
    //new_process.StartInfo.RedirectStandardError = true;
    new_process.StartInfo.UseShellExecute = false;
    new_process.StartInfo.CreateNoWindow = true;
    string line;
    
    void _cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        line = e.Data;
        MyAppendTextBox1(line);
    }
    void _cmd_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        MyAppendTextBox1("err: " + e.Data);
    }
    bool did_start = new_process.Start();
    if (did_start)
    {
        new_process.OutputDataReceived += new DataReceivedEventHandler(_cmd_OutputDataReceived);
        new_process.ErrorDataReceived += new DataReceivedEventHandler(_cmd_ErrorDataReceived);
        //new_process.Exited += new EventHandler(_cmd_Exited);
        new_process.BeginOutputReadLine();
        new_process.BeginErrorReadLine();
    }

    new_process.WaitForExit();

现在,问题是,似乎

tool_exe
本身可能会通过 stderr 和 stdout 重定向做一些奇怪的事情......所以我观察到的是:

  • 如果 RedirectStandardError 不为 true(已注释行) - 那么在运行时,我得到:
System.InvalidOperationException: StandardError has not been redirected.
   at System.Diagnostics.Process.BeginErrorReadLine()

...但除此之外,代码运行良好,文本框实时更新,进程成功退出。

  • 但是,如果我尝试通过取消注释该行并设置 new_process.StartInfo.RedirectStandardError = true 来补救该异常 - 那么,当程序运行时,仅打印一行(_cmd_OutputDataReceived 仅触发一次),然后 C#程序似乎冻结了,并且进程似乎没有退出(所以我必须从 Windows 任务管理器中关闭所有内容)?!

我根本无法想象为什么会发生这种行为(为什么只有当我遇到异常时它才起作用)?!

我唯一注意到的是上面的代码在点击处理程序的上下文中运行;当使用 RedirectStandardError = true 运行构建时,当它冻结时,我实际上看到了一些我原本期望在输出中出现的消息,这些消息显示在 VS2019 的调试输出窗口中(可能在调试对象关闭之后)?

有人知道这里发生了什么吗?我怎样才能无一例外地正常运行?

c# asynchronous io-redirection
1个回答
0
投票

似乎通过这种方式重新组织代码,我可以让它在 stdout 和 stderr 正确重定向的情况下运行,没有异常(但通过以下更改,WaitForExit() 不再起作用:

    Process new_process = new Process();

    new_process.StartInfo.FileName = tool_exe;
    new_process.StartInfo.Arguments = tool_arguments;
    new_process.EnableRaisingEvents = true; // https://stackoverflow.com/q/4504170
    new_process.StartInfo.RedirectStandardInput = true;
    new_process.StartInfo.RedirectStandardOutput = true;
    new_process.StartInfo.RedirectStandardError = true;
    new_process.StartInfo.UseShellExecute = false;
    new_process.StartInfo.CreateNoWindow = true;
    string line;
    
    void _cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        line = e.Data;
        MyAppendTextBox1(line);
    }
    void _cmd_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        MyAppendTextBox1("err: " + e.Data);
    }
    void _cmd_Exited(object sender, EventArgs e)
    {
        new_process.OutputDataReceived -= new DataReceivedEventHandler(_cmd_OutputDataReceived);
        new_process.ErrorDataReceived -= new DataReceivedEventHandler(_cmd_ErrorDataReceived);
        new_process.Exited -= new EventHandler(_cmd_Exited);
    }

    new_process.OutputDataReceived += new DataReceivedEventHandler(_cmd_OutputDataReceived);
    new_process.ErrorDataReceived += new DataReceivedEventHandler(_cmd_ErrorDataReceived);
    new_process.Exited += new EventHandler(_cmd_Exited);

    new_process.Start();
    new_process.BeginOutputReadLine();
    new_process.BeginErrorReadLine();
© www.soinside.com 2019 - 2024. All rights reserved.