首页 文章

ProcessInfo和RedirectStandardOutput

提问于
浏览
27

我有一个应用程序在命令窗口中调用另一个进程,该进程已更新输出到控制台窗口的统计信息 . 我认为这是一个相当简单的操作,但我似乎无法让它工作 . 我错过了什么吗?

string assemblyLocation = Assembly.GetExecutingAssembly().Location;

Process process = new Process
{
    ProcessStart =
    {
        RedirectStandardOutput = true,
        UseShellExecute = false,
        WindowStyle = ProcessWindowStyle.Hidden,
        Arguments = arg,
        FileName = assemblyLocation.Substring(0, assemblyLocation.LastIndexOf("\\")) + "\\ffmpeg.exe",
        CreateNoWindow = true
    }
};

process.Start();

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

process.WaitForExit();

理想情况下,我想要的是输出在我触及的过程中发生变化,或者数据进入读者,我从中得到了事件 .

任何帮助都会很棒,我觉得这是一个新手问题,但似乎缺少一些东西 .

6 回答

  • 1

    我以前经历过这个 . 有时,您调用输出到控制台的进程的方式与此类输出重定向不兼容 . 在这种情况下,我很幸运能够修改外部进程来解决这个问题 .

    您可以尝试在另一个输出到控制台的进程上运行代码,看看它是否正常工作 . 它现在读到我的权利 .

    编辑:

    我去了一个代码块,我曾经这样做过 . 这是在WPF应用程序中,它将进程输出重定向到窗口 . 注意事件绑定 . 由于这是WPF,我必须调用我的调用来写出数据 . 由于您不担心阻塞,因此您应该只需将其替换为:

    Console.WriteLine(e.Data);
    

    希望它有所帮助!

    private static void LaunchProcess()
        {
            Process build = new Process();
            build.StartInfo.WorkingDirectory =  @"dir";
            build.StartInfo.Arguments = "";
            build.StartInfo.FileName = "my.exe";
    
            build.StartInfo.UseShellExecute = false;
            build.StartInfo.RedirectStandardOutput = true;
            build.StartInfo.RedirectStandardError = true;
            build.StartInfo.CreateNoWindow = true;
            build.ErrorDataReceived += build_ErrorDataReceived;
            build.OutputDataReceived += build_ErrorDataReceived;
            build.EnableRaisingEvents = true;
            build.Start();
            build.BeginOutputReadLine();
            build.BeginErrorReadLine();
            build.WaitForExit();
        }
    
        // write out info to the display window
        static void build_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            string strMessage = e.Data;
            if (richTextBox != null && !String.Empty(strMessage))
            {
                App.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Send, (ThreadStart)delegate()
                {
                    Paragraph para = new Paragraph(new Run(strMessage));
                    para.Margin = new Thickness(0);
                    para.Background = brushErrorBrush;
                    box.Document.Blocks.Add(para);
                });
           }
        }
    
  • 21

    我正在运行,但如果你生成了're looking to act on output as soon as it',请尝试挂钩进程的 OutputDataReceived 事件 . 您可以指定处理程序以从进程异步接收输出 . 我成功地使用了这种方法 .

    ProcessStartInfo info = new ProcessStartInfo(...)
    info.UseShellExecute = false;
    info.RedirectStandardOutput = true;
    info.RedirectStandardError = true;
    
    Process p = Process.Start(info);
    p.OutputDataReceived += p_OutputDataReceived;
    p.ErrorDataReceived += p_ErrorDataReceived;
    
    p.BeginOutputReadLine();
    p.BeginErrorReadLine();
    p.WaitForExit();
    

    ..

    void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
      Console.WriteLine("Received from standard out: " + e.Data);
    }
    
    void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
      Console.WriteLine("Received from standard error: " + e.Data);
    }
    

    有关详细信息,请参阅关闭进程OutputDataReceived事件 .

  • 48

    使用lambda表达式等:

    var info = new ProcessStartInfo(path)
    {
        RedirectStandardError = true,
        RedirectStandardOutput = true,
        UseShellExecute = false,
        Verb = "runas",
    };
    
    var process = new Process
    {
        EnableRaisingEvents = true,
        StartInfo = info
    };
    
    Action<object, DataReceivedEventArgs> actionWrite = (sender, e) =>
    {
        Console.WriteLine(e.Data);
    };
    
    process.ErrorDataReceived += (sender, e) => actionWrite(sender, e);
    process.OutputDataReceived += (sender, e) => actionWrite(sender, e);
    
    process.Start();
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();
    process.WaitForExit();
    
  • 11

    有趣的是,您无法同时读取标准输出和标准错误:

    如果您重定向标准输出和标准错误,然后尝试同时读取它们,例如使用以下C#代码 . [C#] string output = p.StandardOutput.ReadToEnd(); string error = p.StandardError.ReadToEnd(); p.WaitForExit();在这种情况下,如果子进程将任何文本写入标准错误,它将阻止该进程,因为父进程无法读取标准错误,直到它完成从标准输出读取 . 但是,在进程结束之前,父进程不会从标准输出读取 . 针对这种情况的推荐解决方案是创建两个线程,以便应用程序可以在单独的线程上读取每个流的输出 .

    http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.71).aspx

  • 4

    流动的代码在VS2010中工作

    void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (String.IsNullOrEmpty(e.Data) == false)
            {
                new Thread(() =>
                {
                    this.Dispatcher.Invoke(new Action(() =>
                    {
                        // Add you code here
                    }));
                }).Start();
            }
        }
    
  • 0

    检查您期望的输出是否未发送到StandardError输出而不是StandardOutput输出

相关问题