diff --git a/src/Artemis.Core/Services/ProcessMonitor/Events/ProcessEventArgs.cs b/src/Artemis.Core/Services/ProcessMonitor/Events/ProcessEventArgs.cs new file mode 100644 index 000000000..dca403a13 --- /dev/null +++ b/src/Artemis.Core/Services/ProcessMonitor/Events/ProcessEventArgs.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; + +namespace Artemis.Core.Services +{ + /// + /// Contains data for the ProcessMonitor process events + /// + public class ProcessEventArgs : EventArgs + { + /// + /// Gets the process related to the event + /// + public Process Process { get; } + + internal ProcessEventArgs(Process process) + { + Process = process; + } + } +} diff --git a/src/Artemis.Core/Services/ProcessMonitor/Interfaces/IProcessMonitorService.cs b/src/Artemis.Core/Services/ProcessMonitor/Interfaces/IProcessMonitorService.cs new file mode 100644 index 000000000..b26376b37 --- /dev/null +++ b/src/Artemis.Core/Services/ProcessMonitor/Interfaces/IProcessMonitorService.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Artemis.Core.Services +{ + /// + /// A service that provides events for started and stopped processes and a list of all running processes. + /// + public interface IProcessMonitorService : IArtemisService + { + /// + /// Occurs when a process starts. + /// + event EventHandler ProcessStarted; + + /// + /// Occurs when a process stops. + /// + event EventHandler ProcessStopped; + + /// + /// Returns an enumerable with the processes running on the system. + /// + IEnumerable GetRunningProcesses(); + } +} diff --git a/src/Artemis.Core/Services/ProcessMonitor/ProcessMonitorService.cs b/src/Artemis.Core/Services/ProcessMonitor/ProcessMonitorService.cs new file mode 100644 index 000000000..86f38e0a1 --- /dev/null +++ b/src/Artemis.Core/Services/ProcessMonitor/ProcessMonitorService.cs @@ -0,0 +1,70 @@ +using Serilog; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Timers; + +namespace Artemis.Core.Services +{ + internal class ProcessMonitorService : IProcessMonitorService + { + private readonly ILogger _logger; + private readonly Timer _processScanTimer; + private readonly ProcessComparer _comparer; + private Process[] _lastScannedProcesses; + + public ProcessMonitorService(ILogger logger) + { + _logger = logger; + _lastScannedProcesses = Process.GetProcesses(); + _processScanTimer = new Timer(1000); + _processScanTimer.Elapsed += OnTimerElapsed; + _processScanTimer.Start(); + _comparer = new ProcessComparer(); + } + + public event EventHandler? ProcessStarted; + + public event EventHandler? ProcessStopped; + + public IEnumerable GetRunningProcesses() + { + return _lastScannedProcesses; + } + + private void OnTimerElapsed(object sender, ElapsedEventArgs e) + { + Process[] newProcesses = Process.GetProcesses(); + foreach (Process startedProcess in newProcesses.Except(_lastScannedProcesses, _comparer)) + { + ProcessStarted?.Invoke(this, new ProcessEventArgs(startedProcess)); + _logger.Debug("Started Process: {startedProcess}", startedProcess.ProcessName); + } + + foreach (Process stoppedProcess in _lastScannedProcesses.Except(newProcesses, _comparer)) + { + ProcessStopped?.Invoke(this, new ProcessEventArgs(stoppedProcess)); + _logger.Debug("Stopped Process: {stoppedProcess}", stoppedProcess.ProcessName); + } + + _lastScannedProcesses = newProcesses; + } + } + + internal class ProcessComparer : IEqualityComparer + { + public bool Equals(Process? x, Process? y) + { + if (x == null && y == null) return true; + if (x == null || y == null) return false; + return x.Id == y.Id && x.ProcessName == y.ProcessName && x.SessionId == y.SessionId; + } + + public int GetHashCode(Process obj) + { + if (obj == null) return 0; + return obj.Id; + } + } +}