ProcessesManagerAspect

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 ;).

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.