Redirect Running Process Output to TextBox - c#

I am trying to Direct the output of any Process given the PID to a Textbox on my Form such as cmd.exe
I use the following code but nothing is happening:
public partial class FormMain : Form
{
private Int32 PID = 0;
private Process process;
public FormMain()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
PID = Convert.ToInt32(textBox2.Text);
process = Process.GetProcessById(PID);
process.OutputDataReceived += process_OutputDataReceived;
}
void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
textBox1.Text += e.Data;
}
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
process.OutputDataReceived -= process_OutputDataReceived;
}
}
What am I doing wrong?

I think the problem with what you are trying to do is with the way you are using the event. The event only fires during async output operations.
You must set:
process.StartInfo.RedirectStandardOutput = true;
Then use async read operations which will fire the event:
process.BeginOutputReadLine();
You should read the documentation for that event:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.outputdatareceived.aspx

Related

How to output data sent through serial port onto a textBox? C# Visual Studio

I'm currently working on a C# application and where I read Serial Data send through the USB port, where this data is to be shown on a textbox then eventually into a database. The code I have right now has it refresh to read serial data coming in every 2 seconds, but I cannot get the data onto the textBox. I'm fairly new to C# development so I am unsure as to what the best way to output my data onto a textbox or how to fix my problem in the first place. My code is below.
public partial class Form1 : Form
{
SerialPort mySerialPort = new SerialPort("COM3");
OleDbConnection connection = new OleDbConnection();
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
if (mySerialPort.IsOpen == false)
{
mySerialPort.Open();
}
}
public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
//gets data values from serial port
SerialPort sp = (SerialPort)sender;
string data = sp.ReadExisting();
string time = GetTimestamp(DateTime.Now);
int indata;
long timeStamp;
//parses strings to integers
indata = Int32.Parse(data);
timeStamp = Int64.Parse(time);
//writes to console
Console.WriteLine(indata);
Console.WriteLine(timeStamp);
//writes to text box
textBox1.Text = data;
Thread.Sleep(2000);
}
private void button3_Click(object sender, EventArgs e)
{
mySerialPort.Close();
}
private void label1_Click(object sender, EventArgs e)
{
}
public static string GetTimestamp(DateTime value)
{
return value.ToString("yyyyMMddHHmmss");
}
private void label1_Click_1(object sender, EventArgs e)
{
}
}
The event DataReceived is handled with the method DataReceivedHandler on a different thread than the control textBox1 is created. So when running your program you should have get a System.InvalidOperationException. Which states exactly what I just described.
To get out of this dilemma you can use the Control.BeginInvoke method which would:
Execute the specified delegate asynchronously on the thread that the control's underlying handle was created on.
Basically it would drag the piece of code down to the thread that cretated the control. In this case the main thread. This is how you would use it:
//writes to text box
textBox1.BeginInvoke(new Action(() => { textBox1.Text = data; }));
I hope it helps.

Exit opened Application

I'd like to know how to exit my opened Application properly.
The way I am currently trying is not working.
This is how I am opening the application:
private void button1_Click(object sender, EventArgs e)
{
if (status != true)
{
status = true;
// Start a process to print a file and raise an event when done.
myProcess.StartInfo.FileName = "C:\\Users\\David\\Desktop\\Test\\Test.exe";
myProcess.Exited += new EventHandler(Process_Exited);
myProcess.EnableRaisingEvents = true;
myProcess.Start();
}
}
private void button2_Click(object sender, EventArgs e)
{
myProcess.Close();
status = false;
}
I've managed to do it, just do:
myProcess.Kill();

Run Code after Child form is closed

so I have this code
public void Update_Click(object sender, EventArgs e)
{
using (PccBiometricsHandler.Form1 ShowProgress = new PccBiometricsHandler.Form1())
{
menu.Items[2].Enabled = false;
ShowProgress.ShowDialog();
ShowProgress.FormClosed += new FormClosedEventHandler(MyForm_FormClosed);
}
}
public void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
updaterAccess();
menu.Items[2].Enabled = true;
}
so after I click Update it will run the child form Form1
which is this:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
notifyIcon1.Visible = true;
notifyIcon1.BalloonTipTitle = "Update Complete";
notifyIcon1.BalloonTipText = "Successfully Update";
notifyIcon1.ShowBalloonTip(500);
timer1.Interval = 4000;
timer1.Enabled = true;
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
notifyIcon1.Dispose();
this.Close();
}
so as you can see it runs on a backgroundworker with a timer to close the child Form1
now my problem is that after closing the Child Form1 it doesn't run the MyForm_FormClosed which it should enable menu.Items[2] again and updaterAccess()
I think I'm missing something in my mainForm
Attached the event handler before firing ShowDialog
public void Update_Click(object sender, EventArgs e)
{
using (PccBiometricsHandler.Form1 ShowProgress = new PccBiometricsHandler.Form1())
{
menu.Items[2].Enabled = false;
ShowProgress.FormClosed += new FormClosedEventHandler(MyForm_FormClosed); //Attached the event handler before firing ShowDialog
ShowProgress.ShowDialog();
}
}
ShowDialog synchronously shows a modal dialog, meaning it blocks until the form is closed (the following code is not run until the form is closed). Therefore, when ShowDialog returns the form is already closed.
You can attach the event handler before calling ShowDialog() as #Jade suggests, which will work, but honestly you do not need to use the event system at all. Simply wait for ShowDialog to return then perform the actions you would when the form is closed:
public void Update_Click(object sender, EventArgs e)
{
using (PccBiometricsHandler.Form1 ShowProgress = new PccBiometricsHandler.Form1())
{
menu.Items[2].Enabled = false;
ShowProgress.ShowDialog();
}
updaterAccess();
menu.Items[2].Enabled = true;
}
If you want to do this in VB:
AddHandler ShowProgress.FormClosed, AddressOf MyForm_FormClosed

SendKeys GUI Bug

I've made this program in C#:
namespace Spammer
{
public partial class Form1 : Form
{
int delay, y = 1;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
delay = int.Parse(textBox2.Text);
timer1.Interval = delay;
timer1.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
String textt = textBox1.Text;
SendKeys.SendWait(textt);
}
}
}
It works fine most of the time, and it can really send keys quickly.
But when I insert a delay of, for example, 10 MS, it's very hard to click the "Stop" button to stop it. The only way to stop the sending is to close the program and I don't want to do that.
Is there anyway I can send keys very quickly, like 5-10 MS, without it impairing my ability to press the buttons inside the program? I can't click while it's sending quickly...
The problem is that you're using SendWait. That will wait for the target application to respond - and while that's happening, your application won't be able to respond to user input. If you use Send instead of SendWait, your UI thread won't be blocked waiting for the key press to be processed.
I was able to reproduce the issue. The app is sending a keystroke every 10 milliseconds. To me, this is not at all surprising that the app is causing freezes. A keystroke every 10 milliseconds is quite a barrage to the active App. Threading is not going to help. Why is this behavior surprising?
In other words, I don't expect things to work out well when I overload the message pump.
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Spammer//your own namesapce
{
public partial class Form1 : Form
{
int delayInMilliseconds, y = 1;
private Timer timer1;
public Form1()
{
InitializeComponent();
//StartTimerWithThreading();
SetupTimer();
}
void StartTimerWithThreading()
{
Task.Factory.StartNew(() =>
{
SetupTimer();
});
}
void SetupTimer()
{
timer1 = new Timer();//Assume system.windows.forms.timer
textBox2.Text = "10";//new delay
timer1.Tick += timer1_Tick;//handler
}
private void button1_Click(object sender, EventArgs e)
{
delayInMilliseconds = int.Parse(textBox2.Text);
timer1.Interval = delayInMilliseconds;
timer1.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
String textt = textBox1.Text;
SendKeys.SendWait(textt);
}
}
}
The simple solution is instead of adding code to a Click event handler for your button, we need a MouseDown event handler:
//MouseDown event handler for the button2
private void button2_MouseDown(object sender, EventArgs e) {
timer1.Enabled = false;
}
Or you can keep using the Click event handler but we send the key only when the MouseButtons is not Left like this:
private void timer1_Tick(object sender, EventArgs e) {
String textt = textBox1.Text;
if(MouseButtons != MouseButtons.Left) SendKeys.Send(textt);
}
//then you can freely click your button to stop it.

why is this backgroundworker code causing this error: Parameter count mismatch

what is wrong with this code below? The conn_PageDeleted is coming from a background thread and i am trying to update a label every time i get a call back. I get an error stating
Parameter count mismatch.
Here is the code:
private void cmdDeletePage_Click(object sender, EventArgs e)
{
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
lblDeleteStatus.Text = "";
MessageBox.Show("Complete");
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
Connecter conn = new Connecter("a", "m");
conn.PageDeleted += new Connecter.PageDeletedHandler(conn_PageDeleted);
bool success = conn.DeletePage(txtPageToDelete.Text, chkRecursive.Checked);
}
public delegate void UpdateLabelHandler(object sender, string name);
void conn_PageDeleted(object sender, string name)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new UpdateLabelHandler(UpdateMe));
}
else
{
lblDeleteStatus.Text = name;
}
}
private void UpdateMe(object sender_, string name_)
{
lblDeleteStatus.Text = name_;
}
You should pass the parameters to the UpdateMe method, try this:
void conn_PageDeleted(object sender, string name)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new UpdateLabelHandler(UpdateMe), new object[] {sender, name}); //<-- the update goes here
}
else
{
lblDeleteStatus.Text = name;
}
}
Your delegate has to match the signature of the event handler, something like this:
public delegate void UpdateLabelHandler(object sender, string strArgs);
Edit: Since you have edited the code to include this ... I will amend this accordingly....
Looking at your edited code, I have to question this:
void worker_DoWork(object sender, DoWorkEventArgs e)
{
Connecter conn = new Connecter("a", "m");
conn.PageDeleted += new Connecter.PageDeletedHandler(conn_PageDeleted);
bool success = conn.DeletePage(txtPageToDelete.Text, chkRecursive.Checked);
}
You are wiring up a 'PageDeleted' event handler....and call 'DeletePage' method after it, I presume that in turn invokes the event handler 'conn_PageDeleted' within the 'DoWork' body, it goes out of scope when the 'BackgroundWorker' thread is finished...and since 'conn' is in local scope of the 'worker_DoWork' method, that gets destroyed, and somehow your event handler gets messed up! Can you confirm this?
Hope this helps,
Best regards,
Tom.

Categories

Resources