Hey, below solution is useful when you create a process and you need to be sure that all your started process by your application will be killed when application end.
So I have two examples. First is a console application usage example.
using System; using System.Diagnostics; using System.Threading; using ProcessesManagerAspectSandbox; namespace ProcessConsole { class Program { static ProcessesManagerAspect processesManagerAspect = new ProcessesManagerAspect(); static void Main(string[] args) { var info = new ProcessStartInfo("notepad.exe"); processesManagerAspect.Start(info); new ProcessesManagerAspect().Start(info); SpinWait.SpinUntil(() => false, 5000); } } }
Second is a WinForms application usage example.
using System; using System.Diagnostics; using System.Windows.Forms; using ProcessesManagerAspectSandbox; namespace ProcessWinForm { static class Program { static ProcessesManagerAspect processesManagerAspect = new ProcessesManagerAspect(); [STAThread] static void Main() { var info = new ProcessStartInfo("notepad.exe"); processesManagerAspect.Start(info); new ProcessesManagerAspect().Start(info); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new EmptyForm()); } } }
And below you can see 85 lines of the ProcesseesManagerAspect implementation.
namespace ProcessesManagerAspectSandbox { using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; public class ProcessesManagerAspect : IDisposable { ConcurrentDictionary<Process, ProcessStartInfo> processes = new ConcurrentDictionary<Process, ProcessStartInfo>(); public Process Start(ProcessStartInfo info) { var process = Process.Start(info); Add(process, info); return process; } void Add(Process process, ProcessStartInfo info) { process.EnableRaisingEvents = true; processes.TryAdd(process, info); process.Exited += (sender, e) => Remove(process); } void Remove(Process process) { ProcessStartInfo info = null; processes.TryRemove(process, out info); } ~ProcessesManagerAspect() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { foreach (var process in processes.Keys) { try { if (!process.HasExited) process.Kill(); } catch { } } } [DllImport("kernel32")] static extern bool SetConsoleCtrlHandler (HandlerRoutine Handler, bool Add); delegate bool HandlerRoutine(CtrlTypes CtrlType); enum CtrlTypes { CTRL_C_EVENT = 0, CTRL_BREAK_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT = 5, CTRL_SHUTDOWN_EVENT } static event Action OnExit; static bool ConsoleCtrlCheck(CtrlTypes ctrlType) { var onExit = OnExit; if (onExit != null) onExit(); return true; } static ProcessesManagerAspect() { SetConsoleCtrlHandler( new HandlerRoutine(ConsoleCtrlCheck), true); } public ProcessesManagerAspect() { OnExit += ProcessesManagerAspectOnExit; } void ProcessesManagerAspectOnExit() { Dispose(); } } }
P ;).