using System; using System.Collections.Generic; using System.Diagnostics; namespace EveOPreview.Services.Implementation { sealed class ProcessMonitor : IProcessMonitor { #region Private constants private const string DefaultProcessName = "ExeFile"; #endregion #region Private fields private readonly IDictionary _processCache; #endregion public ProcessMonitor() { this._processCache = new Dictionary(512); } private bool IsMonitoredProcess(string processName) { // This is a possible extension point return String.Equals(processName, ProcessMonitor.DefaultProcessName, StringComparison.OrdinalIgnoreCase); } public void GetUpdatedProcesses(out ICollection addedProcesses, out ICollection updatedProcesses, out ICollection removedProcesses) { addedProcesses = new List(16); updatedProcesses = new List(16); removedProcesses = new List(16); IList knownProcesses = new List(this._processCache.Keys); foreach (Process process in Process.GetProcesses()) { string processName = process.ProcessName; if (!this.IsMonitoredProcess(processName)) { continue; } IntPtr mainWindowHandle = process.MainWindowHandle; if (mainWindowHandle == IntPtr.Zero) { continue; // No need to monitor non-visual processes } string mainWindowTitle = process.MainWindowTitle; this._processCache.TryGetValue(mainWindowHandle, out string cachedTitle); if (cachedTitle == null) { // This is a new process in the list this._processCache.Add(mainWindowHandle, mainWindowTitle); addedProcesses.Add(new ProcessInfo(mainWindowHandle, mainWindowTitle)); } else { // This is an already known process if (cachedTitle != mainWindowTitle) { this._processCache[mainWindowHandle] = mainWindowTitle; updatedProcesses.Add((IProcessInfo)new ProcessInfo(mainWindowHandle, mainWindowTitle)); } knownProcesses.Remove(mainWindowHandle); } } foreach (IntPtr index in knownProcesses) { string title = this._processCache[index]; removedProcesses.Add(new ProcessInfo(index, title)); this._processCache.Remove(index); } } public ICollection GetAllProcesses() { ICollection result = new List(this._processCache.Count); // TODO Lock list here just in case foreach (KeyValuePair entry in this._processCache) { result.Add(new ProcessInfo(entry.Key, entry.Value)); } return result; } } }