How to parse command line output from c#? - c#

I want to execute an application(command line application) from the C#... and I want after executing this application and providing the input to it, I want to parse the output that will result it. Since, it will output many things, and I want to take, just the things that I need it from it...
How can I do that ??
How can I get the output in the c# and then take only the things I need it from it ??
For executing the command line in C#... I'm thinking to use "Jeff MC" way, that he explained it in this thread
How To: Execute command line in C#, get STD OUT results
Thanks alot

There is one more way of getting all the output as events as and when they are output by the other console application cmd_DataReceived gets raised whenever there is output and cmd_Error gets raised whenever there is an error raised in the other application.
If you want to parse the output, probably handling these events is a better way to read output and handle errors in the other application as and when they occur.
using System;
using System.Diagnostics;
namespace InteractWithConsoleApp
{
class Program
{
static void Main(string[] args)
{
ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
cmdStartInfo.FileName = #"C:\Windows\System32\cmd.exe";
cmdStartInfo.RedirectStandardOutput = true;
cmdStartInfo.RedirectStandardError = true;
cmdStartInfo.RedirectStandardInput = true;
cmdStartInfo.UseShellExecute = false;
cmdStartInfo.CreateNoWindow = true;
Process cmdProcess = new Process();
cmdProcess.StartInfo = cmdStartInfo;
cmdProcess.ErrorDataReceived += cmd_Error;
cmdProcess.OutputDataReceived += cmd_DataReceived;
cmdProcess.EnableRaisingEvents = true;
cmdProcess.Start();
cmdProcess.BeginOutputReadLine();
cmdProcess.BeginErrorReadLine();
cmdProcess.StandardInput.WriteLine("ping www.bing.com"); //Execute ping bing.com
cmdProcess.StandardInput.WriteLine("exit"); //Execute exit.
cmdProcess.WaitForExit();
}
static void cmd_DataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("Output from other process");
Console.WriteLine(e.Data);
}
static void cmd_Error(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("Error from other process");
Console.WriteLine(e.Data);
}
}
}

Related

c# - Throwing Exceptions on Process and StandardOutput.ReadToEnd()

I'm currently in the process of creating a console application that acts as a Video Management Hub. I'm having issues with passing arguments into command line through process. Every time it returns the output from stdout and stderror using appropriate threads for each it's acting as though the Standard.Error.ReadToEnd() and Standard.Out.ReadToEnd() aren't seeing the full arguments after it's waited for the process to exit. Exception returns "is not recognized as an internal or external command, operable program or batch file." Code snippets below show Open method process.
private void Thread_ReadStandardError()
{
if (activeProcess != null)
{
stdErr = activeProcess.StandardError.ReadToEnd();
}
}
private void Thread_ReadStandardOut()
{
if (activeProcess != null)
{
stdOut = activeProcess.StandardOutput.ReadToEnd();
}
}
private string Open(string cmd)
{
string args = "/C [command]";
string temp_path = args.Replace("[command]",cmd);
this.pStartInfo.FileName = "cmd.exe";
this.pStartInfo.Arguments = "\"" + temp_path + "\"";
this.activeProcess.StartInfo = pStartInfo;
this.pStartInfo.CreateNoWindow = true;
this.pStartInfo.UseShellExecute = false;
this.pStartInfo.RedirectStandardOutput = true;
this.pStartInfo.RedirectStandardError = true;
activeProcess = Process.Start(pStartInfo);
Thread thread_ReadStandardError = new Thread(new ThreadStart(Thread_ReadStandardError));
Thread thread_ReadStandardOut = new Thread(new ThreadStart(Thread_ReadStandardOut));
if (pStartInfo.RedirectStandardError)
{
thread_ReadStandardError.Start();
}
if (pStartInfo.RedirectStandardOutput)
{
thread_ReadStandardOut.Start();
}
activeProcess.WaitForExit();
thread_ReadStandardError.Join();
thread_ReadStandardOut.Join();
string output = stdOut + stdErr;
return output;
}
Ultimately I am trying to use a modified version of ExifToolWrapper to run command line arguments to read in video Metadata. I got appropriate arguments/paths prior to my 'Open' method and handle white space before passing in arguments. Process is relatively new to me and prior I was trying to use EnvironmentalVariables to pass in arguments and I get the same output from stdOut+stdErr of
"C:Users###....is not recognized as an internal or external command..."
Is it possibly the way in which my process in setup?

Trying to call Python script in C#

I'm making a mini Python IDE for fun. Why not. So I want to be able to call a python script from C# and right now I'm just testing a simple scenario. I know this is NOT how professional IDE's probably work.
private void Run_Click(object sender, EventArgs e)
{
run_cmd("C:/Python34/python.exe", "C:/Users/Alaseel/Desktop/test.py");
}
private void About_Click(object sender, EventArgs e)
{
// Open the about documentation
}
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:/Python34/python.exe";
start.Arguments = string.Format("{0} {1}", cmd, args);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
Whenever I click the "run" button on the Windows Form app, it briefly runs the python.exe then closes. It does not actually run the file that I passed in. Am I doing something wrong?
PS: The run_cmd method is NOT mine. I looked up this issue previously on a thread and used their code. But I think I'm using the method wrong.
Any ideas? Thank you!
You are actually putting twice your python.exe path in this case. You have it as cmd and start.Filename
Your commandline will look like : "C:/Python34/python.exe" "C:/Python34/python.exe" "C:/Users/Alaseel/Desktop/test.py"
Which is probably an invalid command.

Print standard output of a process to a text box WHILE process is running?

I have a C# GUI from which I run a python script that takes about 2 minutes. Rather than direct the output of the Python script to a file, I'd like to have GUI show all the print-outs that the Python script makes, say, in a text box, as the process is running. Any solution I've found typically waits for the process to end before redirecting the standard output to the text box, and I'm not sure if I'm searching for a solution correctly. Does anyone have an idea about how to do this? Here's some code for reference:
using (Process proc = new Process())
{
debug_output.AppendText("All debug output will be listed below\n");
string pyFileName = "hello.py";
string args = "arg1";
proc.StartInfo.FileName = "C:\\Python27\\python.exe";
proc.StartInfo.Arguments = string.Format("{0} {1}", pyFileName, args);
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.OutputDataReceived += new DataReceivedEventHandler(MyProcOutputHandler);
proc.Start();
proc.BeginOutputReadLine();
while (!proc.HasExited)
{
Application.DoEvents();
}
}
With The following Handler:
private void MyProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
if (!String.IsNullOrEmpty(outLine.Data))
{
if (debug_output.InvokeRequired)
{
debug_output.BeginInvoke(new DataReceivedEventHandler(MyProcOutputHandler), new[] { sendingProcess, outLine });
}
else
{
debug_output.AppendText(outLine.Data);
debug_output.AppendText("\n");
}
}
Console.WriteLine(outLine.Data);
}
As an update, I tried the solution from this post since it looks like the exact same problem, but I still don't get it working. My output ends up in the right place, but only after the whole script is done running. Please help.

Reading StdOut Asynch from a c console app

I have a console based c app .
I am executing it from c# silently using Redirecting Standard Output and doing it synchronously which works fine.
Now i want to do it in asynch manner which is giving output like synch manner.
i.e
OutPutDataRecieved event is fired but only after the console app(exe) finishes.OutputDataRecieved event is fired for each line after finish, not instantly as soon as it gets a line in output.
The code for asynch works for CMD.exe etc ,So,I am sure its c based app having problem in output.
FYI:The output in c console is done using printf.
Based on my findings:
I think c console app is not giving output/writing to stdout until it finishes its execution.
I tried setting buffer to null or flushing after every printf but none works.
Any tricks??
Thanks man.That worked like a charm.
I was using setbuf to set buffer null.
Really appreciate efforts of all you guyz.
FOr info of other guyz,this was my c# code which is available on internet forums and SO too.
string command = #"Output.exe";
string arguments = "hellotext";
ProcessStartInfo info = new ProcessStartInfo(command, arguments);
// Redirect the standard output of the process.
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
// Set UseShellExecute to false for redirection
info.UseShellExecute = false;
Process proc = new Process();
proc.StartInfo = info;
proc.EnableRaisingEvents = true;
// Set our event handler to asynchronously read the sort output.
proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
proc.ErrorDataReceived += new DataReceivedEventHandler(proc_ErrorDataReceived);
proc.Exited += new EventHandler(proc_Exited);
proc.Start();
// Start the asynchronous read of the sort output stream. Note this line!
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
Console.WriteLine("Exited (Main)");
}
static void proc_Exited(object sender, EventArgs e)
{
Console.WriteLine("Exited (Event)");
}
static void proc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("Error: {0}", e.Data);
}
static void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine("Output data: {0}", e.Data);
}
You can disable the buffering using setvbuf.
Here is a quick example, if you remove the call to setvbuf then the redirected content is only written once you press enter (waiting on the getchar()). With the setvbuf, the string is written to the redirected stream directly.
int _tmain(int argc, _TCHAR* argv[])
{
setvbuf(stdout, NULL,_IONBF, 0);
printf("Hello");
getchar();
return 0;
}

Redirect console output to textbox in separate program

I'm developing an Windows Forms application that requires me to call a separate program to perform a task. The program is a console application and I need to redirect standard output from the console to a TextBox in my program.
I have no problem executing the program from my application, but I don't know how to redirect the output to my application. I need to capture output while the program is running using events.
The console program isn't meant to stop running until my application stops and the text changes constantly at random intervals. What I'm attempting to do is simply hook output from the console to trigger an event handler which can then be used to update the TextBox.
I am using C# to code the program and using the .NET framework for development. The original application is not a .NET program.
EDIT:
Here's example code of what I'm trying to do. In my final app, I'll replace Console.WriteLine with code to update the TextBox. I tried to set a breakpoint in my event handler, and it isn't even reached.
void Method()
{
var p = new Process();
var path = #"C:\ConsoleApp.exe";
p.StartInfo.FileName = path;
p.StartInfo.UseShellExecute = false;
p.OutputDataReceived += p_OutputDataReceived;
p.Start();
}
static void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(">>> {0}", e.Data);
}
This works for me:
void RunWithRedirect(string cmdPath)
{
var proc = new Process();
proc.StartInfo.FileName = cmdPath;
// set up output redirection
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.EnableRaisingEvents = true;
proc.StartInfo.CreateNoWindow = true;
// see below for output handler
proc.ErrorDataReceived += proc_DataReceived;
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
// output will be in string e.Data
}
You can use the following code
MemoryStream mem = new MemoryStream(1000);
StreamWriter writer = new StreamWriter(mem);
Console.SetOut(writer);
Assembly assembly = Assembly.LoadFrom(#"C:\ConsoleApp.exe");
assembly.EntryPoint.Invoke(null, null);
writer.Close();
string s = Encoding.Default.GetString(mem.ToArray());
mem.Close();
I've added a number of helper methods to the O2 Platform (Open Source project) which allow you easily script an interaction with another process via the console output and input (see http://code.google.com/p/o2platform/source/browse/trunk/O2_Scripts/APIs/Windows/CmdExe/CmdExeAPI.cs)
Also useful for you might be the API that allows the viewing of the console output of the current process (in an existing control or popup window). See this blog post for more details: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (this blog also contains details of how to consume the console output of new processes)
Thanks to Marc Maxham for his answer that save me time !
As Jon of All Trades notice it, UseShellExecute must be set to false in order to redirect IO streams, otherwise the Start() call throws an InvalidOperationException.
Here is my modification of the code where txtOut is a WPF readonly Textbox
void RunWithRedirect(string cmdargs)
{
var proc = new Process()
{
StartInfo = new ProcessStartInfo("cmd.exe", "/k " + cmdargs)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
},
EnableRaisingEvents = true
};
// see below for output handler
proc.ErrorDataReceived += proc_DataReceived;
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
Dispatcher.BeginInvoke(new Action( () => txtOut.Text += (Environment.NewLine + e.Data) ));
}

Categories

Resources