This is looking like an impossible task. Absolutely nothing I\'ve found works. The question is how to cleanly close a console application started with Process.Start that h
This is a bit late so you might not use it anymore, but perhaps it will help others...
You are overthinking this. The problem is that you can only signal a break from a process that shares the same console - the solution should be rather obvious.
Create a console project. This project will launch the target application the usual way:
var psi = new ProcessStartInfo();
psi.FileName = @"D:\Test\7z\7z.exe";
psi.WorkingDirectory = @"D:\Test\7z\";
psi.Arguments = "a output.7z input.bin";
psi.UseShellExecute = false;
var process = Process.Start(psi);
UseShellExecute
is the important part - this ensures that the two applications are going to share the same console.
This allows you to send the break to your helper application, which will be passed to the hosted application as well:
Console.CancelKeyPress += (s, e) => e.Cancel = true;
Thread.Sleep(1000);
GenerateConsoleCtrlEvent(ConsoleCtrlEvent.CTRL_C, 0);
This will break the hosted application a second after it is started. Easily, safely. The CancelKeyPress
isn't required - I only put it there to make it obvious that you can break the hosted process, and still keep on running. In the real helper application, this could be used for some notifications or something like that, but it's not really required.
Now you only need a way to signal the helper application to issue the break command - the easiest way would be to just use a simple console input, but that might interfere with the hosted application. If that's not an option for you, a simple mutex will work fine:
using (var mutex = Mutex.OpenExisting(args[0]))
using (var processWaitHandle = new SafeWaitHandle(process.Handle, false))
using (var processMre = new ManualResetEvent(false) { SafeWaitHandle = processWaitHandle })
{
var which = WaitHandle.WaitAny(new WaitHandle[] { mutex, processMre });
if (which == 0)
{
Console.WriteLine("Got signalled.");
GenerateConsoleCtrlEvent(ConsoleCtrlEvent.CTRL_C, 0);
}
else if (which == 1)
{
Console.WriteLine("Exitted normally.");
}
}
This will wait either for a signal on the mutex, or for the hosted application to exit. To launch the helper application, all you need to do is this:
var mutexName = Guid.NewGuid().ToString();
mutex = new Mutex(true, mutexName);
var process = Process.Start(@"TestBreak.exe", mutexName);
And to issue the break, just release the mutex:
mutex.ReleaseMutex();
That's it. If you need tighter control, using something like a named pipe might be a better option, but if you only need the break signal, a mutex will do just fine. Any arguments you need to pass can be passed as arguments to the helper application, and you could even make this work with shell scripts (just use the helper application to run anything you need to run and break).