run batch file with Standard Output and Input

G

Gidi

Hi,

In my windows applicationm, i need to excute a batch file.
this batch file throws some text and questions to the screen, i need to
catch the standard Output, check if it's a question, in case it's a question,
i want to popup a messageBox or something, and bring back to the batch file
the result (Yes\No question). I know how to excute the batch file and get all
the Standard output at the end, but i don't know who can i read it line by
line and check if it's a question, and in case it is, bring the result to the
batch file back.

can anyone help me here?

Thanks,
Gidi.
 
G

Gilles Kohl [MVP]

Hi,

In my windows applicationm, i need to excute a batch file.
this batch file throws some text and questions to the screen, i need to
catch the standard Output, check if it's a question, in case it's a question,
i want to popup a messageBox or something, and bring back to the batch file
the result (Yes\No question). I know how to excute the batch file and get all
the Standard output at the end, but i don't know who can i read it line by
line and check if it's a question, and in case it is, bring the result to the
batch file back.

can anyone help me here?

Hmm, check if the sample contained in this MSDN entry helps - sounds
approximately like what you intend to do ...

http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline.aspx

Regards,
Gilles.
 
G

Gidi

Thanks,

but i already read this, and it's not quite helping me, since it's not
executing a batch file, it's just open command line and reading the lines...
it's not what i need...

Thanks again,
Gidi.
 
F

Family Tree Mike

If you know how to read in all the standard output, then just split the
output on newline characters. You then would have the questions and
responses. Perhaps I'm not understanding where you are having the problem.
You should include a small set of code that runs the batch file and reads the
output clarifying where your concern is.
 
G

Gilles Kohl [MVP]

Thanks,

but i already read this, and it's not quite helping me, since it's not
executing a batch file, it's just open command line and reading the lines...
it's not what i need...

You may have noticed that it also sends _input_ to the sort command, not only
captures its output.

This is how you could e.g. set up launching a batch file:

ProcessStartInfo startInfo = new ProcessStartInfo(@"c:\tmp\test.bat");
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;

startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;

m_TheBatch = new Process();
m_TheBatch.StartInfo = startInfo;

m_TheBatch.OutputDataReceived += new
DataReceivedEventHandler(theBatch_OutputDataReceived);
m_TheBatch.Start();
m_TheBatch.BeginOutputReadLine();

(m_TheBatch is a member variable e.g. of your Form and of type Process)


This is what your handling could look like:

void theBatch_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if(e.Data == null)
{
return;
}

string lineRead = e.Data;

if(lineRead.Contains("enter first name now"))
{
m_TheBatch.StandardInput.Write("Gidi\r");
}
}

A problem you'll encounter is that OutputDataReceived is only called for
complete lines. So if your batch file asks for input e.g. this way:

set /p Name=Name?

You won't see the "Name?" prompt line (and won't be able to react to it) as it
does NOT output the CRLF required for OutputDataReceived to be triggered.

In this case, asynchronous reading of lines is indeed not what you need.

Do you need to get this to work for _any_ batch file, or for batch files that
you know? That you could maybe modify to work around the problem above?

I'm asking because a general solution to this problem seems difficult - how in
general tell that the batch is waiting for input? (The stream not having any
characters ready may just mean that it is performing a lengthy operation)

Even more difficult, how to detect where exactly the question that you want to
ask your user is in all the stuff the batch did output?

Before we delve deeper into reading the StandardOutput stream with other
means, can you elaborate on the problem you want to solve - maybe there are
better alternatives?

Regards,
Gilles.
 
G

Gidi

The thing is that my batch file has a certain flow, and i've a question which
detrmain which flow to choose.
so i need to read line by line, and when i get to the question, i want to
display the question to the user and wait for his answer, and send it back to
the batch file and continue to the right flow.

this is my batch file:

@ECHO OFF

ECHO "GOOD MORNING %1%"
:ASK
SET /P ANSWER="Do you want to continue (y/n) ? "
IF "%ANSWER%" == "y" GOTO PRESS_YES
IF "%ANSWER%" == "Y" GOTO PRESS_YES
IF "%ANSWER%" == "n" GOTO PRESS_NO
IF "%ANSWER%" == "N" GOTO PRESS_NO
GOTO ASK

:pRESS_YES
exit 0

:pRESS_NO
exit 1

how can i send the batch file the answer i got?

thanks,
Gidi.
 
F

Family Tree Mike

My recommendation is to not use a batch file at all. If you know the flow
then rewrite the batch file as a routine in your code. If you are required
to use the batch file, then you need to look at redirecting standard input to
the cmd.exe process which launched the batch file.
 
G

Gidi

Hi,

first thanks for the help...

second, at the end, i won't run batch but another exe file, which i've to
use since it's too much work to rewrite all over again to C#...

this is my code for now (while testing it):

private void button1_Click(object sender, EventArgs e)
{
Process pepprocess = new Process();
pepprocess.StartInfo.FileName = "helloworld.bat";
pepprocess.StartInfo.UseShellExecute = false;
pepprocess.StartInfo.RedirectStandardInput = true;
pepprocess.StartInfo.RedirectStandardOutput = true;
pepprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
pepprocess.Start();

StreamWriter sw = pepprocess.StandardInput;
StreamReader rd = pepprocess.StandardOutput;

string line = rd.ReadToEnd();

richTextBox1.Text = line;
if (line.Contains("?") == true)
{
sw.Write("y");
}


Thread.Sleep(1000);


sw.Flush();

}

i tried to read it line by line, but after the first line, the command line
is stuck, and in addition, altough i set the window style to hidden, i still
get the cmd window.

Thanks,
Gidi.
 
F

Family Tree Mike

Here are a few things to change:

1. Batchfiles cannot be the executable process so I'm surprised it
started... I would change the code to do the following:
peprocess.StartInfo.FileName = "cmd.exe";
peprocess.StartInfo.Arguments = "helloworld.bat"

2. Usually the waiting batch prompt is waiting for text and a newline.
Change your statement inside the if (line.contains("?")) to:
sw.WriteLine("y");
 
F

Family Tree Mike

I believe this code will produce the results you want, but I believe there
are better alternatives to this...:

Process pepprocess = new Process();

pepprocess.StartInfo.FileName = "cmd.exe";
pepprocess.StartInfo.Arguments = "/c helloworld.bat";
pepprocess.StartInfo.UseShellExecute = false;
pepprocess.StartInfo.RedirectStandardInput = true;
pepprocess.StartInfo.RedirectStandardOutput = true;
pepprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
pepprocess.StartInfo.CreateNoWindow = true;
pepprocess.Start();

StreamWriter sw = pepprocess.StandardInput;
StreamReader rd = pepprocess.StandardOutput;

while (!rd.EndOfStream)
{
string line = rd.ReadLine ();


richTextBox1.Text = line;
if (line.Contains ( "?" ))
{
sw.WriteLine ( "n" );
}
}

MessageBox.Show ( string.Format ( "{0}",
pepprocess.ExitCode.ToString () ) );
 
G

Gidi

Hi,

thanks so much for the help.
i'm still having problem reading the question line (SET /P ANSWER="Do you
want to continue (y/n) ? ").

the program is stuck at this point.
if i set the pepprocess.StartInfo.RedirectStandardInput to false, so it
works (regardless what the answer was).

do you have any idea?

Thanks so much,
Gidi.
 
G

Gidi

Hi Peter,

thanks.
i guess i posted here old version of my code, this my code now after getting
help here:
Process pepprocess = new Process();

pepprocess.StartInfo.FileName = "cmd.exe";
pepprocess.StartInfo.Arguments = "/c helloworld.bat GIDI";
pepprocess.StartInfo.UseShellExecute = false;
pepprocess.StartInfo.RedirectStandardInput = true;
pepprocess.StartInfo.RedirectStandardOutput = true;
pepprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
pepprocess.StartInfo.CreateNoWindow = true;
pepprocess.Start();

StreamWriter sw = pepprocess.StandardInput;
StreamReader rd = pepprocess.StandardOutput;

while (!rd.EndOfStream)
{
string line = rd.ReadLine();


richTextBox1.Text = line;
if (line.Contains("?"))
{
sw.WriteLine("y");
}
}

the thing is that when i get to the line in my batch file, that expects
input, the process is stuck, and i can't send him the input. if i kill the
process (cmd.exe) then the if statment is commited but it's too late. my
guess is that i should work here with Threads or handlers, but i'm not quit
sure how to do it...

Thanks,
Gidi.

Peter Duniho said:
[...]
string line = rd.ReadToEnd();

richTextBox1.Text = line;
if (line.Contains("?") == true)
{
sw.Write("y");
}
[...]

i tried to read it line by line, but after the first line, the command
line
is stuck,

It should be obvious that you cannot do it that way. You are calling
ReadToEnd() before you write any input. ReadToEnd() will block until the
process you started exits, which isn't going to happen until you've
successfully responded to all prompts.

You've deadlocked your process.

As the MSDN documentation for the Process class does in fact point out, if
you are going to redirect both the input and the output, you need to use
some mechanism for ensuring that you only read as much data as is actually
going to be present and which won't block your thread waiting on more
input. For example, read the output one line at a time, responding as
appropriate with a write to the input when needed.

Pete
 
F

Family Tree Mike

I have no idea, as it is working for me using your batch file as provided in
your earlier message, and my code as provided in my earlier message.
 
G

Gidi

Hi Mike,

i found this article http://www.codeproject.com/KB/cs/ProcessStartDemo.aspx
and it explains how to do what i need.

the code there is very similar to the one you gave me, but there are still
some problems there.
now i'm not running batch file, but exe file which i created in c++, and
displays output and waits for input. if i use the WaitForExit() function, the
process is stuck, if i'm not using it, the process finishes without any
output or input.

do you have any idea?

Thanks again
Gidi.

first
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top