initial checkin of yaulw (locally)
This commit is contained in:
309
Process/ProcessW.cs
Normal file
309
Process/ProcessW.cs
Normal file
@@ -0,0 +1,309 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Diag = System.Diagnostics;
|
||||
using System.Management;
|
||||
|
||||
namespace Yaulw.Process
|
||||
{
|
||||
/// <remarks>
|
||||
/// Wrapper Class around System.Diagnostics's Process Class.
|
||||
/// Helper functions to make sure that we can safely interact with Processes.
|
||||
/// </remarks>
|
||||
public static class ProcessW
|
||||
{
|
||||
#region Process Caching
|
||||
|
||||
/// <summary>
|
||||
/// Process PID Lookup Cache - so that we can cache PIDs, we don't make a new system call
|
||||
/// Use this Property to Cache Process PIDs Lookups
|
||||
/// </summary>
|
||||
public static List<uint> ProcessPidsRunningCache { get { return s_RunningProcessesPids; } }
|
||||
private static List<uint> s_RunningProcessesPids = new List<uint>();
|
||||
|
||||
/// <summary>
|
||||
/// Process Obj Lookup Cache - so that for processes with the same name, we don't make a new system call
|
||||
/// Use this Property to Cache Process Obj Lookups
|
||||
/// </summary>
|
||||
public static Dictionary<string, List<Diag.Process>> ProcessObjsGetterCache { get { return s_processGetterCache; } }
|
||||
private static Dictionary<string, List<Diag.Process>> s_processGetterCache = new Dictionary<string, List<Diag.Process>>();
|
||||
|
||||
/// <summary>
|
||||
/// Clears the Process Obj Lookup Cache - Used in conjuction with AllRunningProcessesOf()
|
||||
/// </summary>
|
||||
public static void ClearProcessObjsGetterCache() { s_processGetterCache.Clear(); }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Query For Processes
|
||||
|
||||
/// <summary>
|
||||
/// Safe GetProcessById Function, to make sure that it returns a valid Process Object
|
||||
/// </summary>
|
||||
/// <param name="PID">the PID to get the Process Object for</param>
|
||||
/// <param name="p">a valid Process obj, or null</param>
|
||||
/// <returns>true if successful, false otherwise</returns>
|
||||
public static bool GetProcessById(int PID, out Diag.Process p)
|
||||
{
|
||||
p = null;
|
||||
try
|
||||
{
|
||||
p = Diag.Process.GetProcessById(PID);
|
||||
return (p != null);
|
||||
}
|
||||
catch (Exception) { /*ignore */ }
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quick Check to see if other Process of that Name Are running
|
||||
/// </summary>
|
||||
/// <param name="ProcessName">name of process</param>
|
||||
/// <param name="bIgnoreVSHost">set to true to ignore Visual Studio's host .exe (debugger process)</param>
|
||||
/// <returns>true, if only one Process of that Name is running, false otherwise</returns>
|
||||
public static bool IsTheOnlyProcessRunning(string ProcessName, bool bIgnoreVSHost = true)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ProcessName))
|
||||
{
|
||||
// Visual Studio could be running this...
|
||||
int nLength1 = Diag.Process.GetProcessesByName(ProcessName).Length;
|
||||
int nLength2 = (bIgnoreVSHost)? 0 : Diag.Process.GetProcessesByName(ProcessName + ".vshost").Length;
|
||||
int nProcessCount = nLength1 + nLength2;
|
||||
return (nProcessCount == 0 || nProcessCount == 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to quickly retrieve all Running PID on this machine
|
||||
/// * Excellent performance 10 MS *
|
||||
/// </summary>
|
||||
/// <returns>returns all running Pids</returns>
|
||||
public static List<uint> AllRunningPids()
|
||||
{
|
||||
Diag.Process[] processes = Diag.Process.GetProcesses();
|
||||
List<uint> allRunningPids = new List<uint>();
|
||||
if (allRunningPids != null)
|
||||
{
|
||||
foreach (Diag.Process p in processes)
|
||||
allRunningPids.Add((uint)p.Id);
|
||||
}
|
||||
return allRunningPids;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all Processes of that ProcessName
|
||||
/// </summary>
|
||||
/// <param name="ProcessName">name of process</param>
|
||||
/// <param name="bUseLookupCache">If true, for .exe's in the Cache will return immediatly without a system call. Use ClearProcessObjsGetterCache() to clear Cache.</param>
|
||||
/// <param name="bIgnoreVSHost">set to true to ignore Visual Studio's host .exe (debugger process)</param>
|
||||
/// <returns>Returns all processes that match the process name, or empty array, if none found</returns>
|
||||
public static Diag.Process[] AllRunningProcessesOf(string ProcessName, bool bUseLookupCache = false, bool bIgnoreVSHost = true)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ProcessName))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Immediatly Return from Cache the Process Getter Calls * Performance Improvement *
|
||||
if (bUseLookupCache && s_processGetterCache.ContainsKey(ProcessName))
|
||||
return s_processGetterCache[ProcessName].ToArray();
|
||||
|
||||
// If a lookup cache is used, we won't deal with the complexity of also dealing with VSHost,
|
||||
// so ignore this setting
|
||||
if (bIgnoreVSHost && bUseLookupCache)
|
||||
bIgnoreVSHost = true;
|
||||
|
||||
// Running Processes found
|
||||
List<Diag.Process> runningProcess = new List<Diag.Process>();
|
||||
|
||||
// Regular Process Lookup...
|
||||
Diag.Process[] processes = Diag.Process.GetProcessesByName(ProcessName);
|
||||
if (processes != null && processes.Length > 0)
|
||||
{
|
||||
foreach (Diag.Process p in processes)
|
||||
runningProcess.Add(p);
|
||||
}
|
||||
|
||||
// Visual Studio could be running this...
|
||||
if (!bIgnoreVSHost)
|
||||
{
|
||||
processes = Diag.Process.GetProcessesByName(ProcessName + ".vshost");
|
||||
if (processes != null && processes.Length > 0)
|
||||
{
|
||||
foreach (Diag.Process p in processes)
|
||||
runningProcess.Add(p);
|
||||
}
|
||||
}
|
||||
|
||||
// Immediatly Cache the Process Getter Calls
|
||||
if (bUseLookupCache && !s_processGetterCache.ContainsKey(ProcessName))
|
||||
{
|
||||
s_processGetterCache[ProcessName] = new List<Diag.Process>();
|
||||
s_processGetterCache[ProcessName].AddRange(runningProcess);
|
||||
}
|
||||
|
||||
// Return the found Processes
|
||||
return runningProcess.ToArray();
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
}
|
||||
return new Diag.Process[0]{}; // return empty array
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Process Exe FileName N CommandLine Getters
|
||||
|
||||
/// <summary>
|
||||
/// Uses WMI to retrieve Process's FileNameNPath and the Command-Line Parameters for the specified Process
|
||||
/// </summary>
|
||||
/// <param name="ProcessId">a valid Pid to retrieve Command-line and Process FileName for</param>
|
||||
/// <param name="ProcessFileNameNPath">passing out full process exe file name and path for pid, if found</param>
|
||||
/// <param name="CommandLineParams">passing out CommandLine params for the Pid, if found</param>
|
||||
/// <returns>true, if the process was found and at least ProcessFileNameNPath was written out, false otherwise</returns>
|
||||
public static bool GetCommandLineArgumentsForProcessPID(int ProcessId, out string ProcessFileNameNPath, out string CommandLineParams)
|
||||
{
|
||||
ProcessFileNameNPath = String.Empty;
|
||||
CommandLineParams = String.Empty;
|
||||
try
|
||||
{
|
||||
// Use WMI to retrieve the info we need (.net does not provide any other way, it appears)
|
||||
string wmiQuery = string.Format("SELECT CommandLine from Win32_Process WHERE ProcessId = {0}", ProcessId);
|
||||
ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiQuery);
|
||||
ManagementObjectCollection retObjectCollection = searcher.Get();
|
||||
if ((retObjectCollection != null) && (retObjectCollection.Count > 0))
|
||||
{
|
||||
foreach (ManagementObject retObject in retObjectCollection) // This will always be only 1 * retObjectCollection doesn't implement []
|
||||
{
|
||||
if (retObject != null) // to be even more save...
|
||||
{
|
||||
string strLocal = String.Empty;
|
||||
if (retObject["CommandLine"] != null && !String.IsNullOrEmpty(retObject["CommandLine"].ToString()))
|
||||
strLocal = retObject["CommandLine"].ToString().Trim();
|
||||
|
||||
if (!String.IsNullOrEmpty(strLocal))
|
||||
{
|
||||
// This should work
|
||||
int firstQuotIndex = strLocal.IndexOf('\"');
|
||||
int SecondQuotIndex = (firstQuotIndex >= 0) ? strLocal.IndexOf('\"', firstQuotIndex + 1) : -1;
|
||||
|
||||
// Pass out * if we at least have a Process FileNameNPath *
|
||||
if (firstQuotIndex > -1 && SecondQuotIndex > -1)
|
||||
{
|
||||
ProcessFileNameNPath = Win32.Functions.GetLongFileNameNPathOrPath(strLocal.Substring(firstQuotIndex + 1, SecondQuotIndex - 1));
|
||||
CommandLineParams = (strLocal.Length > SecondQuotIndex + 2) ? strLocal.Substring(SecondQuotIndex + 2) : String.Empty;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Usefull for making sure that the exact Process Image (including Command-Line Prms) is currently in a running state.
|
||||
/// </summary>
|
||||
/// <param name="runningProcesses">Pass in a list of Process[] where to search for ProcessFileNameNPath and CommandLineParams</param>
|
||||
/// <param name="ProcessFileNameNPath">The exact Process FileName and Path (Image .exe) to find match for</param>
|
||||
/// <param name="CommandLineParams">The exact Command-Line Parameters to find match for</param>
|
||||
/// <param name="PID_Hint">a PID hint * to speed up look * caller can pass in a PID that 'most likely' is the PID we are looking for (Can be zero)</param>
|
||||
/// <param name="process">If we found the process match, we'll pass out the process to the caller (runningProcesses[]), null otherwise</param>
|
||||
/// <param name="indexFound">If we found the process match, we'll pass out the index to the caller (runningProcesses[]), -1 otherwise</param>
|
||||
/// <returns>True, if exact Match was found, False Otherwise</returns>
|
||||
public static bool FoundExactProcessExeNCommandLinePrmsInRunningProcesses(Diag.Process[] runningProcesses, string ProcessFileNameNPath, string CommandLineParams, int PID_Hint, out Diag.Process process, out int indexFound)
|
||||
{
|
||||
process = null;
|
||||
indexFound = -1;
|
||||
try
|
||||
{
|
||||
if (runningProcesses == null || runningProcesses.Length == 0)
|
||||
return false;
|
||||
|
||||
if (PID_Hint < 0)
|
||||
PID_Hint = 0;
|
||||
|
||||
bool bFoundProcessRunning = false;
|
||||
|
||||
// * For Performance Reasons * ProcessW.GetCommandLineArgumentsForProcessPID() takes a long time,
|
||||
// Use PID_Hint first, to check if that PID is it
|
||||
if (PID_Hint > 0)
|
||||
{
|
||||
for (int i = 0; i < runningProcesses.Length; ++i)
|
||||
{
|
||||
Diag.Process rProcess = runningProcesses[i];
|
||||
if (rProcess != null && (rProcess.Id == PID_Hint))
|
||||
{
|
||||
string ProcessFileNameNPath_Local;
|
||||
string CommandLineParams_Local;
|
||||
if (ProcessW.GetCommandLineArgumentsForProcessPID(rProcess.Id, out ProcessFileNameNPath_Local, out CommandLineParams_Local))
|
||||
{
|
||||
// See if we find a match
|
||||
if (ProcessFileExeNCommandLineParamsComparer_FoundMatch(ProcessFileNameNPath_Local, CommandLineParams_Local, ProcessFileNameNPath, CommandLineParams))
|
||||
{
|
||||
bFoundProcessRunning = true;
|
||||
process = rProcess;
|
||||
indexFound = i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PID_Hint Worked, no need to continue...
|
||||
if (bFoundProcessRunning)
|
||||
return bFoundProcessRunning;
|
||||
|
||||
// Iterate all others
|
||||
for (int i = 0; i < runningProcesses.Length; ++i)
|
||||
{
|
||||
Diag.Process rProcess = runningProcesses[i];
|
||||
if (rProcess != null && (rProcess.Id != PID_Hint)) // Ignore PID_Hint * already been tried *
|
||||
{
|
||||
string ProcessFileNameNPath_Local;
|
||||
string CommandLineParams_Local;
|
||||
if (ProcessW.GetCommandLineArgumentsForProcessPID(rProcess.Id, out ProcessFileNameNPath_Local, out CommandLineParams_Local))
|
||||
{
|
||||
// See if we find a match
|
||||
if (ProcessFileExeNCommandLineParamsComparer_FoundMatch(ProcessFileNameNPath_Local, CommandLineParams_Local, ProcessFileNameNPath, CommandLineParams))
|
||||
{
|
||||
bFoundProcessRunning = true;
|
||||
process = rProcess;
|
||||
indexFound = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bFoundProcessRunning;
|
||||
}
|
||||
catch (Exception) { /* ignore */ }
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the passed in ProcessExeFileNameNPath, CommandLinePrms match _Left and _Right
|
||||
/// </summary>
|
||||
/// <param name="ProcessFileNameNPath_Left">Process FileNameNPath to compare to Right</param>
|
||||
/// <param name="CommandLineParams_Left">CommandLine Parameters to compare to Right</param>
|
||||
/// <param name="ProcessFileNameNPath_Right">Process FileNameNPath to compare to Left</param>
|
||||
/// <param name="CommandLineParams_Right">CommandLine Parameters to compare to Left</param>
|
||||
/// <returns>true if _left and _right match, false otherwise</returns>
|
||||
public static bool ProcessFileExeNCommandLineParamsComparer_FoundMatch(string ProcessFileNameNPath_Left, string CommandLineParams_Left, string ProcessFileNameNPath_Right, string CommandLineParams_Right)
|
||||
{
|
||||
if ((String.Compare(ProcessFileNameNPath_Left.Trim(), ProcessFileNameNPath_Right.Trim(), true) == 0) &&
|
||||
(String.Compare(CommandLineParams_Left.Trim(), CommandLineParams_Right.Trim(), true) == 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user