initial checkin of yaulw (locally)

This commit is contained in:
Donald Duck
2016-02-15 12:32:26 -05:00
commit 857eda29e3
115 changed files with 27392 additions and 0 deletions

309
Process/ProcessW.cs Normal file
View 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
}
}