4

How do make a call to a ruby script and pass some parameters and once the script is finished return the control back to the c# code with the result?

2 Answers 2

4
void runScript()
{
    using (Process p = new Process())
    {
        ProcessStartInfo info = new ProcessStartInfo("ruby C:\rubyscript.rb");
        info.Arguments = "args"; // set args
        info.RedirectStandardInput = true;
        info.RedirectStandardOutput = true;
        info.UseShellExecute = false;
        p.StartInfo = info;
        p.Start();
        string output = p.StandardOutput.ReadToEnd();
        // process output
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

This is a terrible answer. It has the classic "deadlock on redirection of both stdout and stderr" problem that the MSDN docs even go to lengths to warn people against. It is awful to write code that redirects both streams and then only consumes one of them.
@PeterDuniho I am not sure what to make of your comment since you have neither provided references nor a suitable fix. Would you recommend just removing the input redirect?
As my comment notes, this information is in the MSDN documentation. See e.g. ProcessStartInfo.RedirectStandardOutput Property. Search for the word "deadlock" on the page. You should have no trouble finding the information. Your code example does exactly what they warn against: redirecting both stdout and stderr, and then not reading either of them asynchronously (your example doesn't even read stderr at all, so it's not clear why you bothered with redirecting it).
2

Just to fill smaller gaps I've implemented the same functionallity with ability to access OutputStream asynchronously.

public void RunScript(string script, string arguments, out string errorMessage)
{
    errorMessage = string.empty;
    using ( Process process = new Process() )
    {
        process.OutputDataReceived += process_OutputDataReceived;
        ProcessStartInfo info = new ProcessStartInfo(script);
        info.Arguments = String.Join(" ", arguments);
        info.UseShellExecute = false;
        info.RedirectStandardError = true;
        info.RedirectStandardOutput = true;
        info.WindowStyle = ProcessWindowStyle.Hidden;
        process.StartInfo = info;
        process.EnableRaisingEvents = true;
        process.Start();
        process.BeginOutputReadLine();
        process.WaitForExit();
        errorMessage = process.StandardError.ReadToEnd();
    }
}

private void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    using ( AutoResetEvent errorWaitHandle = new AutoResetEvent(false) )
    {
        if ( !string.IsNullOrEmpty(e.Data) )
        {
            // Write the output somewhere
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.