/*! GPII Process Reporter processes bridge -- gpii.processes. Copyright 2016 Inclusive Design Research Centre, OCAD University Licensed under the New BSD license. You may not use this file except in compliance with this License. You may obtain a copy of the License at https://github.com/gpii/universal/LICENSE.txt */ using System; using System.Text; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using System.Diagnostics; using System.Dynamic; using System.Management; public class ProcInfo { public string command = ""; public int pid = -1; public string fullPath = ""; public string commandLine = ""; public string state = ""; } public class Startup { public async Task Invoke(dynamic input) { ManagementObject[] processes = null; ArrayList result; ManagementObjectCollection moc = new ManagementClass(new ManagementPath("Win32_Process")).GetInstances(); processes = new ManagementObject[moc.Count]; moc.CopyTo(processes, 0); result = new ArrayList(); // Check input for specified process id or command name. if (input != null) { if (input.GetType() == typeof(System.Int32)) { ManagementObject aProcess = Array.Find( processes, p => Convert.ToInt32(p.GetPropertyValue("ProcessId")) == input ); if (aProcess != null) { makeAndAppendProcInfo(aProcess, result); } } else { ManagementObject[] someProcesses = Array.FindAll( processes, p => string.Equals(p.GetPropertyValue("Name").ToString(), input, StringComparison.OrdinalIgnoreCase) ); foreach (ManagementObject p in someProcesses) { makeAndAppendProcInfo(p, result); } } } // No process specified; get all processes and their info. else { foreach (ManagementObject p in processes) { makeAndAppendProcInfo(p, result); } } return result.ToArray(); } public static void makeAndAppendProcInfo(ManagementObject processMO, ArrayList procInfos) { object propValue; Process theProcess; int pid = Convert.ToInt32(processMO.GetPropertyValue("ProcessId")); // It's possible that the actual process has exited since acquiring its // ManagementObject representation (the argument passed to this // function). If so, trying to get its process id (pid) will result in // an exception indicating the process is no longer running. See: // https://msdn.microsoft.com/en-us/library/76fkb36k(v=vs.110).aspx#Anchor_1 try { theProcess = Process.GetProcessById(pid); ProcInfo procInfo = new ProcInfo(); procInfo.command = processMO.GetPropertyValue("Name").ToString(); procInfo.pid = pid; propValue = processMO.GetPropertyValue("ExecutablePath"); if (propValue != null) { procInfo.fullPath = propValue.ToString(); } propValue = processMO.GetPropertyValue("CommandLine"); if (propValue == null) { propValue = ""; } procInfo.commandLine = propValue.ToString(); // Should be able to get the state of the process using the // "ExecutionState" property, but that is not implemented; see: // http://maestriatech.com/wmi.php // // Use the Process's main thread's state (the first one). // Also, map Windows thread states to Linux-y process states. switch (theProcess.Threads[0].ThreadState) { case ThreadState.Running: case ThreadState.Wait: procInfo.state = "Running"; break; case ThreadState.Initialized: case ThreadState.Ready: case ThreadState.Standby: case ThreadState.Transition: procInfo.state = "Sleeping"; break; case ThreadState.Terminated: case ThreadState.Unknown: procInfo.state = "Zombie"; break; } procInfos.Add(procInfo); } // Process no longer running -- nothing to add. catch (ArgumentException e) { } catch (InvalidOperationException e) { } } }