GUI Winform and ending /killing process - c#

I have a c# GUI app and it's running a bunch of command line process one after another. How do I end/kill the app while the command line process is running?
I have an Exit button (button 3) but it's not working if the process called is still running.
private void Run_Process(string process_to_run, string p_arg)
{
Process myProcess = new Process();
richTextBox1.AppendText("\nRunning " + process_to_run);
try
{
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.FileName = process_to_run;
myProcess.StartInfo.Arguments = p_arg;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
myProcess.WaitForExit();
richTextBox1.AppendText("...Success");
time_date = get_time();
log_file.Write(time_date);
log_file.WriteLine(process_to_run + "...Success");
}
catch (Exception ep)
{
richTextBox1.AppendText("\n" + ep.Message);
time_date = get_time();
log_file.Write(time_date);
log_file.WriteLine(process_to_run + "...Failed. ERROR: " + ep.Message);
}
}
private void button3_Click(object sender, EventArgs e)
{
db.connection.Close();
Application.Exit();
}

Right now, you're waiting for the process to exit:
myProcess.WaitForExit();
If this is happening in the UI thread, then you won't be able to exit (cleanly) until the method finishes, which means you have to wait for the process to finish.
If, instead, you don't wait on the process, you'll be able to exit immediately.
You should be able to rework your logic to not block by setting Process.EnableRaisingEvents and then subscribing to the Exited event on the process. You can add your text to your RichTextBox in this event, instead of blocking the main thread.

You have a call to myProcess.WaitForExit(); in Run_Process. If Run_Process gets called from the main thread, you're going to block that thread until the command line tool finishes. That means button3_Click() can't fire until after myProcess has completed.

If you need to exit, and exit now, try Environment.Exit.
Environment.Exit Method
Terminates this process and gives the underlying operating system the specified exit code.

Environment.Exit(1); really works.

Related

C# Is it possible to close that process?

I have this code:
private void button1_Click(object sender, EventArgs e)
{
Process p = new Process();
string path = AppDomain.CurrentDomain.BaseDirectory + "samp.exe";
string arguments = "arguments...";
p.Exited += new EventHandler(p_Exited);
p.StartInfo.FileName = path;
p.EnableRaisingEvents = true;
p.Start();
}
And
void p_Exited(object sender, EventArgs e)
{
MessageBox.Show("it works");
}
It works, but when I launch samp.exe, the name changes to gta_sa.exe. I want to check if gta_sa.exe process was closed, then close my app.
SHORTLY: I want to make a button. When I click on, it launches samp.exe process, but samp.exe renames to gta_sa.exe, so I need to check if gta_sa.exe process was closed, close my app (Test.exe)
My code is closing samp.exe, but I want to close gta_sa.exe.
It work's, but when launches samp.exe, name changes to gta_sa.exe.
It sounds like samp.exe is a launcher for gta_sa.exe. That is, the first process starts the second process. If samp.exe does not wait for gta_sa.exe to exit, you will have to find the running instance of gta_sa.exe. You can then create a Process instance from the running process and add an event handler for Exited.
P.S my code closing samp.exe, but I wan't to close gta_sa.exe..
No, it is not. Your code is being alerted when samp.exe closes on its own (or for some other reason). If samp.exe is indeed a launcher, its normal behavior would be to close after it starts gta_sa.exe.
If you want to close gta_sa.exe, you can do that using Process.Kill().
You can set an event handler for gta_sa.exe closing like this
var processes = Process.GetProcessesByName("gta_sa.exe");
foreach (var p in processes)
{
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(p_Exited);
}
Make sure you wait to run this code until after gta_sa.exe has been started. Normally there will be only one item in processes, the one process that was launched by samp.exe.
When your samp.exe process exits try to get "gta_sa.exe" process and terminate it:
void p_Exited(object sender, EventArgs e)
{
var processes = Process.GetProcessesByName("gta_sa.exe");
foreach (var process in processes)
process.Kill();
}

How to open .exe files from C# one by one? [duplicate]

I've an application which does
Process.Start()
to start another application 'ABC'. I want to wait till that application ends (process dies) and continue my execution. How can I do it?
There may be multiple instances of the application 'ABC' running at the same time.
I think you just want this:
var process = Process.Start(...);
process.WaitForExit();
See the MSDN page for the method. It also has an overload where you can specify the timeout, so you're not potentially waiting forever.
Use Process.WaitForExit? Or subscribe to the Process.Exited event if you don't want to block? If that doesn't do what you want, please give us more information about your requirements.
I do the following in my application:
Process process = new Process();
process.StartInfo.FileName = executable;
process.StartInfo.Arguments = arguments;
process.StartInfo.ErrorDialog = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
process.Start();
process.WaitForExit(1000 * 60 * 5); // Wait up to five minutes.
There are a few extra features in there which you might find useful...
You could use wait for exit or you can catch the HasExited property and update your UI to keep the user "informed" (expectation management):
System.Diagnostics.Process process = System.Diagnostics.Process.Start("cmd.exe");
while (!process.HasExited)
{
//update UI
}
//done
I had a case where Process.HasExited didn't change after closing the window belonging to the process. So Process.WaitForExit() also didn't work. I had to monitor Process.Responding that went to false after closing the window like that:
while (!_process.HasExited && _process.Responding) {
Thread.Sleep(100);
}
...
Perhaps this helps someone.
Process.WaitForExit should be just what you're looking for I think.
Referring to the Microsoft example:
[https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.enableraisingevents?view=netframework-4.8]
Best would be to set:
myProcess.EnableRaisingEvents = true;
otherwiese the Code will be blocked.
Also no additional properties needed.
// Start a process and raise an event when done.
myProcess.StartInfo.FileName = fileName;
// Allows to raise event when the process is finished
myProcess.EnableRaisingEvents = true;
// Eventhandler wich fires when exited
myProcess.Exited += new EventHandler(myProcess_Exited);
// Starts the process
myProcess.Start();
// Handle Exited event and display process information.
private void myProcess_Exited(object sender, System.EventArgs e)
{
Console.WriteLine(
$"Exit time : {myProcess.ExitTime}\n" +
$"Exit code : {myProcess.ExitCode}\n" +
$"Elapsed time : {elapsedTime}");
}
Like Jon Skeet says, use the Process.Exited:
proc.StartInfo.FileName = exportPath + #"\" + fileExe;
proc.Exited += new EventHandler(myProcess_Exited);
proc.Start();
inProcess = true;
while (inProcess)
{
proc.Refresh();
System.Threading.Thread.Sleep(10);
if (proc.HasExited)
{
inProcess = false;
}
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
inProcess = false;
Console.WriteLine("Exit time: {0}\r\n" +
"Exit code: {1}\r\n", proc.ExitTime, proc.ExitCode);
}
Try this:
string command = "...";
var process = Process.Start(command);
process.WaitForExit();

strange behavior when running process using process class vs cmd c#

I want to run Iperf via c#
when running via cmd everything works fine and fast
but I run it via c# using this code :
public void RunProcess(string FileName, string Arguments, bool EventWhenExit )
{
process = new Process();
process.EnableRaisingEvents = true;
process.OutputDataReceived += new DataReceivedEventHandler(OnDataReceivedEvent);
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.LoadUserProfile = false;
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = FileName; // Gets or sets the application or document to start.
process.StartInfo.Arguments =Arguments;//Gets or sets the set of command-line arguments to use when starting the application
Thread.Sleep(1000);
if (EventWhenExit)
{
process.EnableRaisingEvents = true;
process.Exited += new EventHandler(myprocess_Exited);/*New line */
}
process.Start();
process.BeginOutputReadLine();
PID = process.Id;
}
private void myprocess_Exited(object sender, EventArgs e)
{
process.Refresh();
Thread.Sleep(2000);
onProcessEnd(this, "ENDOF " + Proc.ToString());
Console.WriteLine("Process exsiting ");
}
private void OnDataReceivedEvent(object sender, DataReceivedEventArgs e)
{
string OutputFromProcess = e.Data;
//fire event to event handler class for further use
onDataOutputFromProcess(this, OutputFromProcess, Proc.ToString());
}
I get wrong strange behavior :
when running 1 stream (those of you who use Iperf will know...) every works fine in console and my application (winform)
but I run 3 streams and above , my application wont go over and than just hangs when it should exit
what can be the problem ?
what can be a good work around this problem ?
First you should avoid using Thread.Sleep(x) at any cost.
And i assume you are not using a backgroundWorker or a new Thread to execute the IPerf processes?
I think the backgroundworker would work well for you. Take a look here
In addition:
A cmd program is in most cases very linear.
A WinForm program not. You have to sepereate GUI and Work-Thread.
the GUI is only for Input and Display. Everthing else you should do in another Thread, because otherwise you will block the GUI.

How to start processes sequentially through code

I have to run 3 processes sequentially, one after other. The second process must start after first process' completion.
I work in C#. I have used Process.Start() method, Where it kicks on all at same time.
Can anyone help me.
One way of doing it adding a handler for the Exited event of the first process, and then starting the second process from there.
void StartProcessOne() {
Process p = Process.Start("foo", "bar");
p.Exited += (sender, e) => StartProcessTwo();
p.Start();
}
void StartProcessTwo() {
Process p = Process.Start("foo2", "bar2");
p.Exited += (sender, e) => StartProcessThree();
p.Start();
}
...
You can also use the WaitForExit() method, which waits for the process to end before continuing execution of your code. Note, however, this makes your own process stop execution until the other process terminates. This can leave you with an unresponsive user interface and such, which can be quite undesirable.(source)
Process.Start("yourprogram.exe").WaitForExit();
Process.Start("yournextprogram.exe").WaitForExit();
and so on...
You can accomplish this by responding to the Process.Exited event.
You should use this approach instead of WaitForExit() because the latter will block your program from responding to user input, etc...
private int n = 0;
private void StartAProcess()
{
Process process = new Process {
StartInfo = {FileName = "cmd.exe", Arguments = "pause"},
EnableRaisingEvents = true};
process.Exited += process_Exited;
process.Start();
n++;
}
void process_Exited(object sender, EventArgs e)
{
if (n < 3) StartAProcess();
}
try this code for each process
Process.WaitForExit()
http://msdn.microsoft.com/en-us/library/aa326953(v=VS.71).aspx
If you are using .NET 4 you could use the System.Threading.Tasks API. If your graph gets more complex you may get some mileage from http://pdag.codeplex.com (I must confess, this is my work).
You need to do a process.join() to wait for the first process to complete before submitting the next one. However, the bigger question is why you are using Process.Start() - for asynchronous tasks - when you actually want them to run synchronously? Just calling:
a();
b();
c();
will run them one after another.

Run code when current process terminates?

Is there a way to run a bit of code when the current process is getting terminated?
I want to log some stuff when a process terminates (either through external means - eg killing it - or quitting in the application itself).
We're talking about a Console application written in c#.
Thanks!
Have a look here: atexit, exit delegate in c#
I am not sure, but something similar would help
Process process = new Process();
.
.
process.Exited += new EventHandler(myProcess_Exited);
process.Start();
private void myProcess_Exited(object sender, System.EventArgs e)
{
eventHandled = true;
customAction(); // your logging stuff here
}
public void customAction()
{
//
}
have a look at: Process.Exited Event

Categories