9

I am trying to call php-cgi.exe from a .NET program. I use RedirectStandardOutput to get the output back as a stream but the whole thing is very slow.

Do you have any idea on how I can make that faster? Any other technique?

    Dim oCGI As ProcessStartInfo = New ProcessStartInfo()
    oCGI.WorkingDirectory = "C:\Program Files\Application\php"
    oCGI.FileName = "php-cgi.exe"
    oCGI.RedirectStandardOutput = True
    oCGI.RedirectStandardInput = True
    oCGI.UseShellExecute = False
    oCGI.CreateNoWindow = True

    Dim oProcess As Process = New Process()

    oProcess.StartInfo = oCGI
    oProcess.Start()

    oProcess.StandardOutput.ReadToEnd()
Vincent
  • 22,366
  • 18
  • 58
  • 61
  • You might be interested in [this post](http://www.codeducky.org/process-handling-net), which covers many of the intricacies of working with .NET process streams. It recommends the [MedallionShell](https://github.com/madelson/MedallionShell) library, which vastly simplifies this sort of task, and can use async to prevent blocking – ChaseMedallion Aug 29 '14 at 11:22

3 Answers3

19

The best solution I have found is:

private void Redirect(StreamReader input, TextBox output)
{
    new Thread(a =>
    {
        var buffer = new char[1];
        while (input.Read(buffer, 0, 1) > 0)
        {
            output.Dispatcher.Invoke(new Action(delegate
            {
                output.Text += new string(buffer);
            }));
        };
    }).Start();
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    process = new Process
    {
        StartInfo = new ProcessStartInfo
        {
            CreateNoWindow = true,
            FileName = "php-cgi.exe",
            RedirectStandardOutput = true,
            UseShellExecute = false,
            WorkingDirectory = @"C:\Program Files\Application\php",
        }
    };
    if (process.Start())
    {
        Redirect(process.StandardOutput, textBox1);
    }
}
Jader Dias
  • 88,211
  • 155
  • 421
  • 625
  • you're right, this solution is resellient but it's importance is not clear until you go through the problem you described in the comment on the question – Ahmed Khalaf Jul 26 '10 at 12:22
  • can you fork or tee the output so it goes to shell execute and your process at the same time? http://stackoverflow.com/questions/9525171/can-i-fork-the-output-streams-of-a-process-im-starting/9525264#comment12080971_9525264 – Maslow Mar 02 '12 at 17:08
8

You can use the OutputDataReceived event to receive data as it's pumped to StdOut.

Bob King
  • 25,372
  • 6
  • 54
  • 66
  • Just a side note, I would redirect standard error with the OutputDataReceived event as well. You could then throw a new exception or handle the error in another way. – Tom Alderman Oct 03 '08 at 00:34
  • 8
    @Vincent @Bob King The problem with this event is that it only is called when a the output receives a newline. My solution in another answer in this thread works also when the output has no carriage returns nor newlines. – Jader Dias Feb 15 '10 at 18:40
2

The problem is due a bad php.ini config. I had the same problem and i downloaded the Windows installer from: http://windows.php.net/download/.

After that and commenting out not needed extensions, the conversion process is alà Speedy Gonzales, converting 20 php per second.

You can safely use "oProcess.StandardOutput.ReadToEnd()". It's more readable and alomost as fast as using the thread solution. To use the thread solution in conjunction with a string you need to introduce an event or something.

Cheers

Martin.Martinsson
  • 1,894
  • 21
  • 25