【问题标题】:Get another application standart output in realtime实时获取另一个应用程序标准输出
【发布时间】:2016-10-12 06:33:40
【问题描述】:

我想通过我的 WinForm 应用程序实时获取控制台应用程序的输出(与通过 cmd.exe 运行相同)。我在非 UI 线程中执行的所有操作(使用 BackgroundWorker 的方法 bwRezerve_DoWork)。 AddTextToTextbox 使用 Invoke 更新 UI。

但现在我只在应用程序退出时才收到输出。 我在这里和其他网站上阅读了很多问题,阅读了类似的问题Capture output of process synchronously (i.e. "when it happens"),但仍然找不到解决方案。 这里代码sn-p:

private void bwRezerve_DoWork(object sender, DoWorkEventArgs e)
{
    proc = new Process
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = Application.StartupPath + Path.DirectorySeparatorChar + "7z.exe",
            Arguments = e.Argument,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true,
        }
    };
    proc.EnableRaisingEvents = true;
    proc.OutputDataReceived += (who, what) => AddTextToTextbox(what.Data);
    proc.ErrorDataReceived += (who, what) => AddTextToTextbox(what.Data);

    proc.Start();
    proc.BeginOutputReadLine();
    proc.BeginErrorReadLine();
    //same result with next line commented
    proc.WaitForExit(5 * 60 * 1000);
}

我也试过这个而不是OutputDataReceived,但结果是一样的

while (!proc.StandardOutput.EndOfStream)
{
    string line = proc.StandardOutput.ReadLine();
    AddTextToTextbox(line);
}

【问题讨论】:

    标签: c# winforms process real-time stdout


    【解决方案1】:

    试试这个代码

    private void bwRezerve_DoWork(object sender, DoWorkEventArgs e)
    {
        ProcessStartInfo psi = new ProcessStartInfo();
        psi.FileName = Application.StartupPath + Path.DirectorySeparatorChar + "7z.exe";
        psi.Arguments = e.Argument;
        psi.UseShellExecute = false;
        psi.RedirectStandardError = true;
        psi.RedirectStandardOutput = true;
        psi.CreateNoWindow = true;
    
        Process proc = Process.Start(psi);
        proc.WaitForExit();
    
        while (!proc.StandardOutput.EndOfStream)
        {
           string line = proc.StandardOutput.ReadLine();
           AddTextToTextbox(line);
        }
    }
    

    【讨论】:

    • 在这种情况下,我根本没有收到任何输入。
    • 我已经使用了 ReadLine() 和 ReadToEnd() - 结果还是一样。
    • 新的更新是我刚刚在我的机器上检查过的工作代码
    • 同样的结果。从代码中很容易看出 - 在进程退出之前我没有收到任何更新:proc.WaitForExit(); 在 stdOut 读取之前。如果proc.WaitForExit(); 在读取输出之后,结果相同。
    【解决方案2】:

    我认为你的线程有问题你的进程在主线程下运行,所以你的输出只会在进程完成时显示。 所以你需要使用后台工作者或线程,你也可以使用调度程序从当前进程获取输出。

    while (!proc.StandardOutput.EndOfStream)
    {
    
      Application.Current.Dispatcher.Invoke(new Action(() =>
         {
        string line = proc.StandardOutput.ReadLine();
        AddTextToTextbox(line);
         }), null);
    
    }
    

    希望它对你有用..

    编辑

    您可以使用当前调度程序 窗口基础库。

    程序集: WindowsBase(在 WindowsBase.dll 中)(Ref MSDN)

    System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(new Action(() =>
                {
                    string line = proc.StandardOutput.ReadLine();
                    AddTextToTextbox(line);
                }), null);
    

    【讨论】:

    • 我不能使用“Application.Current.Dispatcher.Invoke”,因为它是 WinForms 项目,而不是 WPF。但是我在 BackgroundWorker (bwRezerve_DoWork) 中执行的所有操作。在“AddTextToTextbox”方法中,我使用 Invoke 在 UI 线程中执行更新。
    • 我不需要进步,我需要得到输出(那里)。并且控制台应用程序本身不发送百分比。
    • 相同的结果 - 控制台应用程序退出后显示输出(是的,WaitForExit() 在 thi 代码块之后)。
    【解决方案3】:

    7zip 不使用标准输出 - 你可以很容易地看到,因为它不断地重写屏幕(以显示进度)。没有办法流式传输。

    【讨论】:

    • 但是 7zip 以某种方式将数据发送到 cmd.exe,不是吗?我想捕捉这些数据。
    • @Varro 不,cmd 与它无关 - 这只是一个命令处理器。它将数据直接发送到控制台,如果您在应用程序中创建控制台,它将像cmd 一样显示输出。如果您不创建控制台,则不会获得输出。 stdout 默认显示在控制台中,但这并不意味着控制台中显示的所有内容都通过 stdout :)
    • @Varro C# 中的等价物是例如当您执行 Console.CursorTop = 0 时 - 现在您正在写入控制台缓冲区而不是标准输出。现在,基础架构已经足够智能,您最终会在标准输出中获得输出,但它根本无法为您提供任何会改变的东西 - 标准输出没有“倒带”功能,它只是一个流.
    • 你确定吗?根据 7zip 帮助(与此处 sevenzip.osdn.jp/chm/cmdline/switches/bs.htm 相同),默认情况下它将标准输出消息重定向到标准输出流。
    • @Varro 你可以自己看看。标准输出仅附加 - 7z 的控制台输出是否仅附加?使用> x.x 在cmd 中运行7z。在解压缩过程中,文件是否立即包含您想要的最新内容(显然,尝试使用大文件)?不,因为数据尚未在标准输出上 - 仅在控制台中(重定向标准输出时控制台输出被禁用)。 -bd 开关应该已经解决了这个问题,但实际上似乎没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 2017-02-03
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 2017-11-10
    相关资源
    最近更新 更多