Best way to interact with Command Line application
Asked Answered
A

3

8

I need to write a component for an application that interacts tightly with a command line application. The command line application asks a series of questions, performs some computations, then terminates (which i need to detect). Essentially, i want to wrap up this interaction in a wrapper class.

Has any one achieved similar in the past? If so, how did you go about it? Did you notice a pattern, or maybe some good build in classes to use? Cheers!

Agathaagathe answered 14/1, 2009 at 11:47 Comment(0)
D
18

You would need to redirect both the input and output streams, using Process; it is slightly trickier handling both, since you need to be careful that things aren't lost in the buffers (causing deadlock).

You might also want to look at OutputDataReceived for event-based responses.

Duplex answered 14/1, 2009 at 11:49 Comment(0)
R
5

I get dinged when my responses are just links to elsewhere. I don't see where the link to the C# Corner article helps much.

The question is 10 years old today but it should have been clarified. The question does not specify whether there are line endings (CrLf) at the end of each question. Assuming there are, as in the following:

string Answer;
Console.Out.WriteLine("First question: ");
Answer = Console.In.ReadLine();
Console.Out.WriteLine("Another question: ");
Answer = Console.In.ReadLine();
Console.Out.WriteLine("Final question: ");
Answer = Console.In.ReadLine();

Then the following can be used to respond to it:

class Program
{
    const string FirstQuestion = "First question: ";
    const string SecondQuestion = "Another question: ";
    const string FinalQuestion = "Final question: ";
    static AutoResetEvent Done = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        const string TheProgram = @" ... ";
        Process p = new Process();
        ProcessStartInfo psi = new ProcessStartInfo(TheProgram);
        psi.UseShellExecute = false;
        psi.CreateNoWindow = true;
        psi.RedirectStandardInput = true;
        psi.RedirectStandardOutput = true;
        p.StartInfo = psi;
        Console.WriteLine("Executing " + TheProgram);
        p.Start();
        DoPromptsAsync(p);
        Done.WaitOne();
    }

    private static async Task DoPromptsAsync(Process p)
    {
        StreamWriter sw = p.StandardInput;
        StreamReader sr = p.StandardOutput;
        string Question;
        Question = await sr.ReadLineAsync();
        if (Question != FirstQuestion)
            return;
        sw.WriteLine("First answer");
        Console.WriteLine(Question + "answered");
        Question = await sr.ReadLineAsync();
        if (Question != SecondQuestion)
            return;
        sw.WriteLine("Second answer");
        Console.WriteLine(Question + "answered");
        Question = await sr.ReadLineAsync();
        if (Question != FinalQuestion)
            return;
        sw.WriteLine("Final answer");
        Console.WriteLine(Question + "answered");
        Done.Set();
    }
}

The following works in a WPF application; I used a double-click event to test but this could be used in other WPF events.

const string TheProgram = @" ... ";
Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo(TheProgram);
psi.UseShellExecute = false;
//psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
p.StartInfo = psi;
p.Start();
const string FirstQuestion = "First question: ";
const string SecondQuestion = "Another question: ";
const string FinalQuestion = "Final question: ";
StreamWriter sw = p.StandardInput;
StreamReader sr = p.StandardOutput;
string Question;
StringBuilder sb = new StringBuilder("Executing " + TheProgram + "\r\n");
Question = await sr.ReadLineAsync();
if (Question != FirstQuestion)
    return;
sw.WriteLine("First answer");
sb.Append(Question + "answered\r\n");
Question = await sr.ReadLineAsync();
if (Question != SecondQuestion)
    return;
sw.WriteLine("Second answer");
sb.Append(Question + "answered\r\n");
Question = await sr.ReadLineAsync();
if (Question != FinalQuestion)
    return;
sw.WriteLine("Final answer");
sb.Append(Question + "answered\r\n");
ResultBox.Text = sb.ToString();

I think it will be more complicated if there are not line endings after each question.

Rummer answered 15/1, 2019 at 2:52 Comment(0)
T
1

If all applications are developed in dotnet you can use Assembly class

Trottier answered 14/1, 2009 at 12:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.