C# Is it possible to close that process? - c#

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

Related

How to get a process started by another process I started?

I know the title is alittle confusing but I have a problem with getting a certain process that gets created by a process I start in my code and here is what I mean ..
private void BtnUNINSTALLG_Click(object sender, EventArgs e)
{
LoadingGif1.Visible = true;
Process p = Process.Start(#"C:\program files\XXXX\XXXX\XXX\XXXX.exe");
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(UNINSTALL_Exited);
}
private void UNINSTALL_Exited(object sender, System.EventArgs e)
{
Invoke(new Action(() => {
LoadingGif1.Visible = false;
DoneGif1.Visible = true;
}));
}
What I do here is I start a process and after it exits I do some stuff .. but that doesn't work because this process create temp.exe ( changes name every time ) in temp folder and the process I started exits right after this temp process created.
I want to get the temp process created by the process I started and then wait until it exits instead of the process I started. Does anyone have any idea how can I do that ?

GUI Winform and ending /killing process

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.

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.

cmd.exe style application written in C#

I am trying to get the results from any DOS-based application, effectively letting C# operate it as if it were a user.
I can get it to execute a command, and then show the output. The problem is knowing when the output has ended! For example, if I go start/run "cmd.exe", type "D:", then "cd D:\", and then "tree", it outputs my folder structure on the D drive, and then allows me to type my next command (only after it's finished printing the list).
However I can't find a way in code to get it to realise it's finished, and should allow the next command (basically when cmd.exe starts blinking your cursor).
public Process p = null;
private void Form1_Load(object sender, System.EventArgs e)
{
ProcessStartInfo procStarter = new ProcessStartInfo("cmd.exe");
procStarter.RedirectStandardOutput = true;
procStarter.RedirectStandardInput = true;
procStarter.UseShellExecute = false;
procStarter.CreateNoWindow = true;
p = Process.Start(procStarter);
}
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
p.Close();
}
private void btnSend_Click(object sender, System.EventArgs e)
{
p.StandardInput.WriteLine("D:");
p.StandardInput.WriteLine(#"cd D:\");
txtOutput.Text = SendCommand(txtInput.Text);
}
private string SendCommand(string cmd)
{
p.StandardInput.WriteLine(cmd);
return p.StandardOutput.ReadToEnd();
}
In SendCommand(string cmd), if I run p.StandardOutput.ReadToEnd(), as per the code above, it hangs forever, presumably waiting for the application to close?
If I loop through p.StandardOutput.ReadLine(), it shows all the text (including the "D:\>" just before where the blinking cursor would then be, however it doesn't realise it's the end, calls ReadLine again, and hangs in a smiliar fashion to ReadToEnd. A dirty workaround would be to treat it as the end of the response if the current line ends with ">", however that falls apart if a line ends like that anywhere in the response.
I've tried looping through the stream character by character, and there's no special character sent at the end.
Any ideas?
Note: My ultimate goal is to provide a light library I can use for executing any DOS executable (which may require several typed commands passed to it, not just the one off arguments passed via command line on opening), parsing the results returned with a regex template, and returning the extracted result. I figured if I can effectively re-implement the cmd.exe in a windows application, then such a library will be possible.
Thanks,
Lee
I suspect that your approach doesn’t work. cmd.exe is not going to communicate to you via StandardOutput when or whether the command you ran has finished or not. (I should point out though that this doesn’t stop you from running multiple commands. You can probably just send the command lines and don’t actually need to wait for it to finish.)
Perhaps a more suitable approach might be not to use cmd.exe at all. Instead, use Process.Start() to run each individual command. Then you can use StandardOutput.ReadToEnd() and it will finish when the process is finished, and you can run the next one.
I agree with Timwi, But see if something like below helps
ProcessStartInfo procStarter = new ProcessStartInfo("cmd.exe");
procStarter.RedirectStandardOutput = true;
procStarter.RedirectStandardInput = true;
procStarter.UseShellExecute = false;
procStarter.CreateNoWindow = true;
procStarter.WorkingDirectory = #"D:\";
procStarter.Arguments = "/C dir";
Process p = Process.Start(procStarter);
string output = p.StandardOutput.ReadToEnd();
/C command line to cmd.exe will terminate cmd.exe once the work is done. You can also use p.Exited (exited event) to know when it happens.
However it will not keep the cmd.exe always running. But do you really need to keep it running?
If you're looking for 'how to wait till the spawned process terminates', Process.WaitForExit is what should do the trick.
You could spawn a new shell for each "command".
About a year ago I wrote a telnet server for windows that allowed the remote user to issue commands against cmd.exe. Maybe you can use it as a starting point for your own project.
Get the code on my blog
By reading the output asynchronous I have gotten this to work (aleast almost) like you described:
public Process p = null;
private void Send_Click(object sender, System.EventArgs e)
{
p.StandardInput.WriteLine("D:");
p.StandardInput.WriteLine(#"cd D:\");
p.StandardInput.WriteLine(txtInput.Text);
}
private void Form1_Load_1(object sender, EventArgs e)
{
ProcessStartInfo procStarter = new ProcessStartInfo("cmd.exe");
procStarter.RedirectStandardOutput = true;
procStarter.RedirectStandardInput = true;
procStarter.UseShellExecute = false;
procStarter.CreateNoWindow = true;
p = Process.Start(procStarter);
p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
p.BeginOutputReadLine();
}
void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
addTextToOutput(e.Data);
}
private void addTextToOutput(string text)
{
if (txtOutput.InvokeRequired)
{
addTextCallback cb = new addTextCallback(addTextToOutput);
this.Invoke(cb, new Object[] { text });
}
else
{
txtOutput.Text += text+ System.Environment.NewLine;
}
}
delegate void addTextCallback(String text);
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
p.Close();
}

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