Get Values from Process Standardoutput

Get Values from Process StandardOutput

You have to read both the standard output and standard error streams. This is because you can't read them both from the same thread.

To achieve this you have to use the eventhandlers that will be called on a separate thread.

Compile the code as anycpu as openfiles comes in a 32-bit and 64-bit variant. It might not find the executable if there is an architecture mismatch.

The lines that are read from the error stream are prepended with ! > so they stand out in the output.

    StringCollection values = new StringCollection();
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "openfiles.exe",
Arguments = "/query /FO CSV /v",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = false
}
};
proc.Start();

proc.OutputDataReceived += (s,e) => {
lock (values)
{
values.Add(e.Data);
}
};
proc.ErrorDataReceived += (s,e) => {
lock (values)
{
values.Add("! > " + e.Data);
}
};

proc.BeginErrorReadLine();
proc.BeginOutputReadLine();

proc.WaitForExit();
foreach (string sline in values)
MessageBox.Show(sline);

Get and Set the position in Process.StandardOutput

I found the answer, to open the file in subdirectory just use this cli.StartInfo.FileName = Directory.GetCurrentDirectory() + @"\SubfolderName\fantasygold-cli";

and the arguements like getbalance as cli.StartInfo.Arguments = "getbalance amunim"

process.StandardOutput.ReadToEnd() does not get the total StandardOutput

You should also hook into Process.StandardError

string error = p.StandardError.ReadToEnd();

Get Live output from Process

Take a look at this page, it looks this is the solution for you: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline.aspx and http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput.aspx

[Edit]
This is a working example:

        Process p = new Process();
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = @"C:\Program Files (x86)\gnuwin32\bin\ls.exe";
p.StartInfo.Arguments = "-R C:\\";

p.OutputDataReceived += new DataReceivedEventHandler((s, e) =>
{
Console.WriteLine(e.Data);
});
p.ErrorDataReceived += new DataReceivedEventHandler((s, e) =>
{
Console.WriteLine(e.Data);
});

p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();

Btw, ls -R C:\ lists all files from the root of C: recursively. These are a lot of files, and I'm sure it isn't done when the first results show up in the screen.
There is a possibility 7zip holds the output before showing it. I'm not sure what params you give to the proces.

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();

Read Process StandardOutput before New Line Received

Here is a solution of your problem but a little bit tricky, because gdalwarp.exe is blocking standart output, you can redirect its output to a file and read changes on it. It was possible to use FileSystemWatcher to detect changes in file but it is not reliable enough sometimes. A simple polling method of file size changes is used below in the outputReadThread if OutputCallback is not null.

Here is a call to ExecuteProcess with callback to receive process output immediately.

    public static void ResizeTiff(string SourceFile, string DestinationFile, float ResolutionWidth, float ResolutionHeight, Guid ProcessId)
{
var directory = GDalBin;
var exe = Path.Combine(directory, "gdalwarp.exe");
var args = " -ts " + ResolutionWidth + " " + ResolutionHeight + " -r cubic -co \"TFW=YES\" \"" + SourceFile + "\" \"" + DestinationFile + "\"";
float progress = 0;
Action<string, string> callback = delegate(string fullOutput, string newOutput)
{
float value;
if (float.TryParse(newOutput, out value))
progress = value;
else if (newOutput == ".")
progress += 2.5f;
else if (newOutput.StartsWith("100"))
progress = 100;
};
ExecuteProcess(exe, args, null, directory, 0, null, true, true, 0, callback);
}

Here is a function to call any process and receive the results as they happen.

    public static string ExecuteProcess(string FilePath, string Args, string Input, string WorkingDir, int WaitTime = 0, Dictionary<string, string> EnviroVariables = null, bool Trace = false, bool ThrowError = true, int ValidExitCode = 0, Action<string, string> OutputChangedCallback = null)
{
var processInfo =
"FilePath: " + FilePath + "\n" +
(WaitTime > 0 ? "WaitTime: " + WaitTime.ToString() + " ms\n" : "") +
(!string.IsNullOrEmpty(Args) ? "Args: " + Args + "\n" : "") +
(!string.IsNullOrEmpty(Input) ? "Input: " + Input + "\n" : "") +
(!string.IsNullOrEmpty(WorkingDir) ? "WorkingDir: " + WorkingDir + "\n" : "") +
(EnviroVariables != null && EnviroVariables.Count > 0 ? "Environment Variables: " + string.Join(", ", EnviroVariables.Select(a => a.Key + "=" + a.Value)) + "\n" : "");

string outputFile = "";
if (OutputChangedCallback != null)
{
outputFile = Path.GetTempFileName();
Args = "/C \"\"" + FilePath + "\" " + Args + "\" >" + outputFile;
FilePath = "cmd.exe";
}

var startInfo = (string.IsNullOrEmpty(Args))
? new ProcessStartInfo(FilePath)
: new ProcessStartInfo(FilePath, Args);

if (!string.IsNullOrEmpty(WorkingDir))
startInfo.WorkingDirectory = WorkingDir;

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

if (OutputChangedCallback == null)
{
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
}
else
{
startInfo.RedirectStandardOutput = false;
startInfo.RedirectStandardError = false;
}

if (!string.IsNullOrEmpty(Input))
startInfo.RedirectStandardInput = true;

if (EnviroVariables != null)
foreach (KeyValuePair<String, String> entry in EnviroVariables)
startInfo.EnvironmentVariables.Add(entry.Key, entry.Value);

var process = new Process();
process.StartInfo = startInfo;
if (process.Start())
{
if (Trace)
Log.Debug("Running external process with the following parameters:\n" + processInfo);

try
{
if (!string.IsNullOrEmpty(Input))
{
process.StandardInput.Write(Input);
process.StandardInput.Close();
}
var standardError = "";
var standardOutput = "";
int exitCode = 0;

Thread errorReadThread;
Thread outputReadThread;

if (OutputChangedCallback == null)
{
errorReadThread = new Thread(new ThreadStart(() => { standardError = process.StandardError.ReadToEnd(); }));
outputReadThread = new Thread(new ThreadStart(() => { standardOutput = process.StandardOutput.ReadToEnd(); }));
}
else
{
errorReadThread = new Thread(new ThreadStart(() => { }));
outputReadThread = new Thread(new ThreadStart(() =>
{
long len = 0;
while (!process.HasExited)
{
if (File.Exists(outputFile))
{
var info = new FileInfo(outputFile);
if (info.Length != len)
{
var content = new StreamReader(File.Open(outputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)).ReadToEnd();
var newContent = content.Substring((int)len, (int)(info.Length - len));
len = info.Length;
OutputChangedCallback.Invoke(content, newContent);
}
}
Thread.Sleep(10);
}
}));
}

errorReadThread.Start();
outputReadThread.Start();

var sw = Stopwatch.StartNew();
bool timedOut = false;
try
{
while (errorReadThread.IsAlive || outputReadThread.IsAlive)
{
Thread.Sleep(50);
if (WaitTime > 0 && sw.ElapsedMilliseconds > WaitTime)
{
if (errorReadThread.IsAlive) errorReadThread.Abort();
if (outputReadThread.IsAlive) outputReadThread.Abort();
timedOut = true;
break;
}
}

if (!process.HasExited)
process.Kill();

if (timedOut)
throw new TimeoutException("Timeout occurred during execution of an external process.\n" + processInfo + "Standard Output: " + standardOutput + "\nStandard Error: " + standardError);

exitCode = process.ExitCode;
}
finally
{
sw.Stop();
process.Close();
process.Dispose();
}

if (ThrowError && exitCode != ValidExitCode)
throw new Exception("An error was returned from the execution of an external process.\n" + processInfo + "Exit Code: " + exitCode + "\nStandard Output: " + standardOutput + "\nStandard Error: " + standardError);

if (Trace)
Log.Debug("Process Exited with the following values:\nExit Code: {0}\nStandard Output: {1}\nStandard Error: {2}", exitCode, standardOutput, standardError);

return standardOutput;
}
finally
{
FileUtilities.AttemptToDeleteFiles(new string[] { outputFile });
}
}
else
throw new Exception("The process failed to start.\n" + processInfo);
}


Related Topics



Leave a reply



Submit