Process.start: how to get the output?
Solution 1
When you create your Process
object set StartInfo
appropriately:
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "program.exe",
Arguments = "command line arguments to your executable",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
then start the process and read from it:
proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
// do something with line
}
You can use int.Parse()
or int.TryParse()
to convert the strings to numeric values. You may have to do some string manipulation first if there are invalid numeric characters in the strings you read.
Solution 2
You can process your output synchronously or asynchronously.
1. Synchronous example
static void runCommand()
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR"; // Note the /c command (*)
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
//* Read the output (or the error)
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
string err = process.StandardError.ReadToEnd();
Console.WriteLine(err);
process.WaitForExit();
}
Note that it's better to process both output and errors: they must be handled separately.
(*) For some commands (here StartInfo.Arguments
) you must add the /c
directive, otherwise the process freezes in the WaitForExit()
.
2. Asynchronous example
static void runCommand()
{
//* Create your Process
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
//* Start process and handlers
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
//* Do your stuff with the output (write to console/log/StringBuilder)
Console.WriteLine(outLine.Data);
}
If you don't need to do complicate operations with the output, you can bypass the OutputHandler method, just adding the handlers directly inline:
//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
Solution 3
Alright, for anyone who wants both Errors and Outputs read, but gets deadlocks with any of the solutions, provided in other answers (like me), here is a solution that I built after reading MSDN explanation for StandardOutput
property.
Answer is based on T30's code:
static void runCommand()
{
//* Create your Process
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
//* Set ONLY ONE handler here.
process.ErrorDataReceived += new DataReceivedEventHandler(ErrorOutputHandler);
//* Start process
process.Start();
//* Read one element asynchronously
process.BeginErrorReadLine();
//* Read the other one synchronously
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
process.WaitForExit();
}
static void ErrorOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
//* Do your stuff with the output (write to console/log/StringBuilder)
Console.WriteLine(outLine.Data);
}
Solution 4
The standard .NET way of doing this is to read from the Process' StandardOutput stream. There is an example in the linked MSDN docs. Similar, you can read from StandardError, and write to StandardInput.
Solution 5
It is possible to get the command line shell output of a process as described here : http://www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx
This depends on mencoder. If it ouputs this status on the command line then yes :)
stighy
Updated on July 08, 2022Comments
-
stighy almost 2 years
I would like to run an external command line program from my Mono/.NET app. For example, I would like to run mencoder. Is it possible:
- To get the command line shell output, and write it on my text box?
- To get the numerical value to show a progress bar with time elapsed?
-
codea over 10 yearsI was wondering how you could deal with StandardError ?. BTW I really like this code snippet ! nice and clean.
-
codea over 10 yearsThanks,But I think I was not clear: Should I add another loop to do so ?
-
Ferruccio over 10 years@codea - I see. You can create one loop that terminates when both streams reach EOF. That can get a little complicated because one stream will inevitably hit EOF first and you don't want to read from it anymore. You could also use two loops in two different threads.
-
Gusdor over 10 yearsis it more robust to read until the process itself terminates, rather than waiting for end of streams?
-
Ferruccio over 10 years@Gusdor - I don't think so. When the process terminates, its streams will automatically be closed. Also, a process may close its streams long before it terminates.
-
Richard Barker over 8 yearsgotta love async! I was able to use this code (with a little transcribing) in VB.net
-
T30 about 7 yearsThanks for adding this. Can I ask what command you were using?
-
cubrman about 7 yearsI am developing an app in c# that is designed to launch a mysqldump.exe, show the user every single message the app generates, wait for it to finish and then perform some more tasks. I can't understand what kind of command you are talking about? This entire question is about launching a process from c#.
-
Andrew Hill almost 7 yearsnote 'string output = process.StandardOutput.ReadToEnd();' may produce a large string if there is many lines of output; the async example, and the answer from Ferruccio both process the output line by line.
-
S.Serpooshan over 6 yearsNote: your first (synchronous) approach is not correct! You should NOT read both StandardOutput and StandardError synchronously! it will cause dead-locks. atleast one of them must be async.
-
Tom over 6 yearsProcess.WaitForExit() is thread blocking, thus synchronous. Not the point of the answer, but I thought I might add this. Add process.EnableRaisingEvents = true and make use of the Exited event to be fully asynchronous.
-
ovi about 6 yearsif you use two separate handlers you will not get deadlocks
-
ovi about 6 yearsalso in you example, you read the process.StandardOutput only once... right after you start it, but one would want to read it continuously while the process is running, no?
-
Anirudha Gupta almost 6 yearsI am trying to use this code on Ffmpeg, any help, stuck in find out the processes work is completed.
-
Ini over 4 yearsIs it not possible to directly redirect? I use all colorization of the sass output?
-
Samuel over 4 yearsYou are missing a dispose.
-
ygoe over 3 years@S.Serpooshan Can you explain this? I wouldn't know why that should be the case. To T30: The above async code isn't safe if you need to take the full output when the process exits. Those events keep coming in after the process has exited and the program has moved on. There's no indication whether the data is complete. If in doubt, the output data will always be incomplete! Seen this here. I'm not sure if async is a good solution in this case.
-
Eric Wood over 3 years@Curbman, I think T30 was asking "what command" because you are firing the process called "cmd.exe" .
-
SYB almost 3 yearsBest example I've found! Thanks
-
Wai Ha Lee almost 3 yearsStrongly related: ProcessStartInfo hanging on “WaitForExit”? Why?
-
Evgeny Gorbovoy over 2 yearsexceptions caught by general catch(Exception) must be re-thrown, otherwise it swallows the exception which can be awaited by "upper" code. In the given example the debugger will not stop on exception if it happened inside
try
block -
Sphynx over 2 yearsProbably worth mentioning that the Standard Error of the child process ought to go to the Standard Error of this application (e.g. via
using (var standardErrorStreamWriter = new StreamWriter(Console.OpenStandardError())) standardErrorStreamWriter.Write(e.Data);
).Console.WriteLine
writes to the Standard Output instead. -
k1dfr0std over 2 yearsThis is fantastic. Similar to @RichardBarker, I too was able to use this with some transcribing into VB.Net, and this works EXACTLY how I needed it to! Adding Event Handlers for each
OutputDataReceived
andErrorDataReceived
and appending the data to Public StringBuilders (using them for multiple shell commands) has allowed me to hook the StdOut/StdErr data and process it to provide feedback to my users! WONDERFUL STUFF! -
Emma Thapa about 2 yearsThis saved my day, made my day too. thank you.