Click to See Complete Forum and Search --> : Capture console and output in realtime
algrn912005
September 10th, 2008, 08:30 PM
Here's what I want to do:
I want to open a console window with the push of a button and then capture the window output into my gui. This console window will be closed on user termination so I need the output capture to continuously work until program termination. I have tried the redirect standard output methods but it waits until the program exits and then shows the output.
If anyone could help me, that would be great.
algrn912005
September 11th, 2008, 05:39 PM
anyone?
MNovy
September 12th, 2008, 12:11 AM
the only way I know is, to start another console application and redirect its output to a variable, which can be displayed in the WinForm GUI.
This is done by:
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = fileName;
p.StartInfo.Arguments = arguments;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = false; // true;
p.Start();
string sOutput = p.StandardOutput.ReadToEnd();
p.Wait...();
int exitCode = p.ExitCode;
p.Close();
//richTextBox_Output.Text = sOutput;
return exitCode;
Arjay
September 12th, 2008, 01:39 AM
Handle the OutputDataReceived event.
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += new DataReceivedEventHandler( process_OutputDataReceived );
process.Start( );
process.WaitFor.Exit( timeout );
void process_OutputDataReceived( object sender, DataReceivedEventArgs e )
{
// Std output arrives here
}
algrn912005
September 13th, 2008, 05:18 PM
Handle the OutputDataReceived event.
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += new DataReceivedEventHandler( process_OutputDataReceived );
process.Start( );
process.WaitFor.Exit( timeout );
void process_OutputDataReceived( object sender, DataReceivedEventArgs e )
{
// Std output arrives here
}
I see that you use process.waitfor.exit(). Doesn't that mean it has to wait for the exit of the application. I do not want it to wait for the application to finish. I want it to continuously work until the user presses a button to terminate the program.
This is more of what I wanted to do:
Public Class Form1
Private WithEvents tb As New TextBox
Sub New()
InitializeComponent()
Me.Text = "click the textbox"
Me.Controls.Add(tb)
tb.Dock = DockStyle.Fill
tb.ReadOnly = True
tb.ScrollBars = ScrollBars.Both
tb.Multiline = True
Me.Width = 500
End Sub
Sub Go()
Dim p As New Process
p.StartInfo.FileName = "ping.exe"
p.StartInfo.Arguments = "www.bbc.co.uk"
p.StartInfo.UseShellExecute = False
p.StartInfo.RedirectStandardOutput = True
AddHandler p.OutputDataReceived, AddressOf HelloMum
p.Start()
p.BeginOutputReadLine()
End Sub
Sub HelloMum(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
UpdateTextBox(e.Data)
End Sub
Private Delegate Sub UpdateTextBoxDelegate(ByVal Text As String)
Private Sub UpdateTextBox(ByVal Tex As String)
If Me.InvokeRequired Then
Dim del As New UpdateTextBoxDelegate(AddressOf UpdateTextBox)
Dim args As Object() = {Tex}
Me.Invoke(del, args)
Else
tb.Text &= Tex & Environment.NewLine
End If
End Sub
Private Sub tb_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles tb.Click
Go()
End Sub
End Class
But that's in VB.net. Could someone help me get it into C#?
Thanks again for the help.
Arjay
September 13th, 2008, 06:47 PM
I see that you use process.waitfor.exit(). Doesn't that mean it has to wait for the exit of the application.No, the OutputDataReceived handler will still get called. You can take the Wait*****it line out but you need to declare the process on the class level, not within a function.
See the attached zip file for an example. I've created two apps: a winforms app (called CGStdOutput) that uses the process class to launch an app called CGDir. The CGDir app just grabs the system directory and writes the file names to the console window (i.e std output). The CGStdOutput launches the CGDir app and set an OutputDataReceived handler to put the std output (i.e. the filenames from the CGDir app) into a listbox.
CGDir code:
static void Main( string[ ] args )
{
DirectoryInfo di = new DirectoryInfo( Environment.SystemDirectory );
foreach( FileInfo fileInfo in di.GetFiles( ) )
{
Console.WriteLine( fileInfo.ToString( ) );
}
}
CGStdOutput code:
public partial class Form1 : Form
{
public Form1( )
{
InitializeComponent( );
}
private void _btnRun_Click( object sender, EventArgs e )
{
_btnRun.Enabled = false;
if( null != _process )
{
_process.Dispose( );
}
_process = new Process( );
_process.StartInfo.FileName = "CGDir.exe";
_process.StartInfo.UseShellExecute = false;
_process.EnableRaisingEvents = true;
_process.StartInfo.CreateNoWindow = true;
_process.StartInfo.RedirectStandardOutput = true;
_process.OutputDataReceived += new DataReceivedEventHandler( OnOutputDataReceived );
_process.Exited += new EventHandler( OnProcessExited );
_process.Start( );
_process.BeginOutputReadLine( );
}
/// <summary>
/// Standard Output event handler - called when standard output text is available from
/// the launched process.
/// This event handler gets called from a different thread than the main UI thread.
/// As such we need to use a delegate to access the UI thread.
/// </summary>
void OnOutputDataReceived( object sender, DataReceivedEventArgs e )
{
if( _listBox.InvokeRequired && !String.IsNullOrEmpty( e.Data ) )
{
// We use an anonymous delegate here
_listBox.Invoke( new MethodInvoker( delegate( ) { _listBox.Items.Add( e.Data ); } ) );
}
}
/// <summary>
/// Called when process exits
/// </summary>
void OnProcessExited( object sender, EventArgs e )
{
if( _btnRun.InvokeRequired )
{
// We use an anonymous delegate here
_btnRun.Invoke( new MethodInvoker( delegate( ) { _btnRun.Enabled = true; } ) );
}
}
private Process _process = null;
}
SoftwareTester
September 14th, 2008, 01:56 AM
I don't know if this is exactly what you want but there is a way to redirect console output to a ricktextbox and it works at mine.
public partial class MDIParent : Form
{
private StringRedir RedirConsole;
private TextWriter ConsoleWriter;
public MDIParent()
{
InitializeComponent();
// Here we redirect Console.WriteLine to a RichTextBox control.
ConsoleWriter = Console.Out; // Save the current console TextWriter.
RedirConsole = new StringRedir(ref rtbOutput);
Console.SetOut(RedirConsole); // Set console output to the StringRedir class.
}
private void MDIParent_OnDestroy()
{
Console.SetOut(ConsoleWriter); // Redirect Console back to original TextWriter.
RedirConsole.Close(); // Close our StringRedir TextWriter.
}
}
public class StringRedir : StringWriter
{ // Redirecting Console output to RichTextBox
private RichTextBox outBox;
delegate void Writeline(string x);
public StringRedir(ref RichTextBox textBox)
{
outBox = textBox;
}
public override void Write(string value)
{ // Centralize output in ONE function : this one
outBox.Text += value;
outBox.Refresh();
}
public override void WriteLine(string value)
{
Write(value + "\n");
}
public override void Write(string format, params object[] args)
{
Write(string.Format(format, args));
}
public override void WriteLine(string format, params object[] args)
{
Write(string.Format(format, args) + "\n");
}
}
(BTW This code is not mine : I found it on the net because I looked for it myself some time ago)
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.