I have a windows form that creates multiple console applications of the same program (it calls program.exe any number of times) using
process.start().
I am looking for a way to identify a specific running of the application and kill it cleanly (ie cleanly close the 5th process of program.exe but leave all other processes running). I am able to identify each different process of program.exe through ids that were given when the processes were started, but I am unable to close the application any way other than calling
process.kill()
which does not perform a clean close of the application.
I believe that I cannot use
process.CloseMainWindow()
since the application does not have a window (it is run through a console that runs in the background). I am looking to kill the processes by clicking a button in my GUI after I select the process to be killed from a list of the processes that are running.
The reason why I need this is because I need to close all threads and outstanding aspects of each process before it closes.
I define each new process as follows,
Process process = new Process();
process.StartInfo = info;
ExecutionDetails details = new ExecutionDetails(run_id, process, info, session_type, strategy_type, name, ExecutionViewModel);
lock (_runs)
_runs.Add(run_id, details); // will throw on Add if duplicate id, prevent duplicate
ExecutionViewModel.NewRun(details); // add to the view model
process.Start();
Where run_id is a GUID that identifies each process.
In a seperate class I have the code that is executed through the process which is only referenced through the command prompt that starts the program (ie calls program, provides config variables, etc).
Is there any way that I can close the processes cleanly? I was thinking that having an event that is called when I want to kill the process might work but so far I have not been able to get that idea to work since I am unable to specify which process I want closed.
** EDIT - My code for the event handling that I have tried to impliment but it is not working.
Code In Main Window
public void KillOne() {
foreach (var details in _runs.Values) {
if(details.IsSelected) {
StrategyStateManager.SessionClosed(this, details.RunId);
} } }
Code in StrategyStateManager (Middle class used to hold variables and events to use in program)
public delegate void StrategyCloseEventHandler(object sender, StrategyCloseEventArgs e);
public static void SessionClosed(object sender, Guid id)
{
if(CloseSession != null)
CloseSession(sender, new StrategyCloseEventArgs(id));
}
public class StrategyCloseEventArgs : EventArgs
{
private readonly Guid id;
public StrategyCloseEventArgs(Guid run_id)
{
id = run_id;
}
public Guid GetRunID()
{
return id;
}
}
Code in process that is being started by main window
StrategyStateManager.CloseSession += (closeStrategy);
void closeStrategy(object sender, StrategyCloseEventArgs e)
{
if (e.GetRunID() == run_id)
{
strategy.cleanupForShutdown();
DBSaverSimple.shutdownAll();
logger.Warn("Simulation run stopped by user");
}
}
The simplest method to avoid this is to start the application from Visual Studio without using debugging. You do so by selecting "Start Without Debugging" from the Debug menu or by pressing Ctrl-F5. When the program stops executing, you must press a key before the console window closes.
A console application is a computer program designed to be used via a text-only computer interface, such as a text terminal, the command-line interface of some operating systems (Unix, DOS, etc.) or the text-based interface included with most graphical user interface (GUI) operating systems, such as the Windows Console ...
The possibility that comes immediately to mind is to use a broadcast datagram that contains a close message and the process id of the one that you want closed. Each of the console processes listens for broadcast datagrams on a common port. When the program receives a datagram, it parses the data, checks the passed process id against its own process id, and if they match, the program initiates a clean shutdown.
This assumes, of course, that you have created a way for the program to shut itself down cleanly.
Broadcast datagrams aren't guaranteed to be received, of course, but my experience has been that they're reliable on a single system. If you run into a problem, you could have your main program send the datagram, wait some period of time to see if the program has shut down, and if not then send the datagram again.
Another possibility is to create a named EventWaitHandle
for each process that you start, passing the name of that event to the console application on the command line. The console program could then have a thread that does a WaitOne
on that event. When the event is set, the program initiates a clean shutdown. This is more reliable than the broadcast datagram. Sure, it uses another handle per process, but that won't be a problem unless you have thousands of processes.
See Send message from one running console app to another for an example of using a named wait handle to communicate between processes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With