Process.start: how to get the output?
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.
C# Process.Start: how to read output?
Firstly, you are checking for process.HasExited
in a while loop.
This, of course will be false by default, and then your code will just skip this. That is why I suggest using an asynchronous method or an event-based aproach.
If you choose asynchronous, you can do this:
using (var process = Process.Start(psi))
{
errors = await process.StandardError.ReadToEndAsync();
results = await process.StandardOutput.ReadToEndAsync();
}
here, psi
is an instance of ProcessStartInfo
.
You set them after creating the process, but you can create an object and pass that in the constructor.
If you cannot make it asynchronous, you can do:
using (var process = Process.Start(psi))
{
errors = process.StandardError.ReadToEndAsync().Result;
results = process.StandardOutput.ReadToEndAsync().Result;
}
How to get the output of a System.Diagnostics.Process?
What you need to do is capture the Standard Output stream:
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
string q = "";
while ( ! p.HasExited ) {
q += p.StandardOutput.ReadToEnd();
}
You may also need to do something similar with StandardError
. You can then do what you wish with q
.
It is a bit finicky, as I discovered in one of my questions
As Jon Skeet has pointed out, it is not smart performance-wise to use string concatenation like this; you should instead use a StringBuilder
:
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
StringBuilder q = new StringBuilder();
while ( ! p.HasExited ) {
q.Append(p.StandardOutput.ReadToEnd());
}
string r = q.ToString();
Capturing standard out and error with Start-Process
That's how Start-Process
was designed for some reason. Here's a way to get it without sending to file:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "ping.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "localhost"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode
Process.Start does not output the full output
It seems the issue was with PsExec itself (a Sysinternal utility) as I have tried an alternative called PAExec and the same command works fine, so I am using this one in my code instead.
How to get log from Process.Start
Set your ProcessStartInfo.RedirectStandardOutput
to true
- this will redirect all output to Process.StandardOutput
, which is a stream that you can read to find all output messages:
ProcessStartInfo process = new ProcessStartInfo
{
CreateNoWindow = false,
UseShellExecute = false,
WorkingDirectory = msPath,
RedirectStandardOutput = true,
FileName = msCompiler,
Arguments = "-p {0} -v / {1}"
.StrFormat(
CurrentSetting.CodeSource,
CurrentSetting.CompileTarget)
};
Process p = Process.Start(process);
string output = p.StandardOutput.ReadToEnd();
You can also use the OutputDataReceived
event in a similar way to what @Bharath K describes in his answer.
There are similar properties/events for StandardError
- you will need to set RedirectStandardError
to true
as well.
Using Process.Start to capture console output
Given the description:
you would remove the event subscription and the call to
process.BeginOutputReadLine()
he is talking about those two lines:
process.OutputDataReceived += (o, e) => { if (e.Data == null) mreOut.Set(); else output(e.Data); };
process.BeginOutputReadLine();
Note that the code you substitute to this should be just:
new ReadOutput(process.StandardInput, mreOut);
ReadOutput
class would be outside the Run
method (since in C#, methods cannot contain classes).
Related Topics
How to Generate a Random Integer in C#
Should 'Using' Directives Be Inside or Outside the Namespace
Set Object Property Using Reflection
Dependency Inject (Di) "Friendly" Library
Best Way to Get Application Folder Path
Quickest Way to Convert a Base 10 Number to Any Base in .Net
Easiest Way to Split a String on Newlines in .Net
Copy the Entire Contents of a Directory in C#
Find All Controls in Wpf Window by Type
Is There a String Math Evaluator in .Net
How to Create a New Object Instance from a Type
Difference Between Task and Thread
Using New Unity Videoplayer and Videoclip API to Play Video