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

110
Process/PStartInfo.cs Normal file
View File

@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using Yaulw.Tools;
namespace Yaulw.Process
{
/// <remarks>
/// Helper Class to create ProcessStartInfo Objects
/// </remarks>
public static class PStartInfo
{
/// <summary>
/// Creates a simple ProcessStartInfo Object
/// </summary>
/// <param name="ExeFileNPath">Exe File and Path to execute</param>
/// <param name="CmdLine">CmdLine Params to process, optional</param>
/// <param name="bUseRunAs">If true, will set "RunAs" For the Process, to Run as Administrator</param>
/// <param name="WindowStyle">the windows style to initialize main window with</param>
/// <param name="bUseShellExecute">True to use Explorer.exe shellexecute, false otherise</param>
/// <returns>a ProcessStartInfo Object or null if error occured</returns>
public static ProcessStartInfo CreateProcess(string ExeFileNPath, string CmdLine = "", string WorkingDir = "", bool bUseRunAs = false, ProcessWindowStyle WindowStyle = ProcessWindowStyle.Normal, bool bUseShellExecute = true)
{
if (!String.IsNullOrEmpty(ExeFileNPath) && System.IO.File.Exists(ExeFileNPath))
{
ProcessStartInfo startInfo = new ProcessStartInfo(ExeFileNPath, CmdLine);
startInfo.WindowStyle = WindowStyle;
startInfo.UseShellExecute = bUseShellExecute;
if (bUseRunAs)
startInfo.Verb = "runas";
// Set up Working Directory, if one is found
if(!String.IsNullOrEmpty(WorkingDir))
startInfo.WorkingDirectory = PathNaming.PathEndsWithSlash(WorkingDir);
else
startInfo.WorkingDirectory = Path.GetDirectoryName(ExeFileNPath);
return startInfo;
}
return null;
}
/// <summary>
/// Creates an url ProcessStartInfo Object
/// </summary>
/// <param name="url">url to launche</param>
/// <returns>a ProcessStartInfo Object or null if error occured</returns>
public static ProcessStartInfo LaunchUrl(string url)
{
if (!String.IsNullOrEmpty(url))
{
ProcessStartInfo startInfo = new ProcessStartInfo(url);
startInfo.UseShellExecute = true;
return startInfo;
}
return null;
}
/// <summary>
/// Creates a CMD.Exe CommandLine Executable ProcessStartInfo Object
/// </summary>
/// <param name="scriptFileNPath">Full FileName and Path to script file to execute via CMD.exe</param>
/// <param name="bUseRunAs">If true, will set "RunAs" For the Process, to Run as Administrator</param>
/// <returns>a ProcessStartInfo Object or null if error occured</returns>
public static ProcessStartInfo CreateCMDScriptProcess(string scriptFileNPath, bool bUseRunAs = false)
{
if (!String.IsNullOrEmpty(scriptFileNPath) && System.IO.File.Exists(scriptFileNPath))
{
//The "/C" Tells Windows to Run The Command then Terminate
string strCmdLine = "/C " + '\"' + scriptFileNPath + '\"';
string WindowsSystem32Folder = System.Environment.GetFolderPath(Environment.SpecialFolder.System);
ProcessStartInfo startInfo = new ProcessStartInfo((WindowsSystem32Folder + "\\" + "CMD.exe"), strCmdLine);
//startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
if (bUseRunAs)
startInfo.Verb = "runas";
startInfo.WorkingDirectory = Path.GetDirectoryName(scriptFileNPath);
return startInfo;
}
return null;
}
/// <summary>
/// Creates a CMD.Exe CommandLine Executable ProcessStartInfo Object
/// </summary>
/// <param name="DosCommand">Dos Command to Execute</param>
/// <param name="bUseRunAs">If true, will set "RunAs" For the Process, to Run as Administrator</param>
/// <returns>a ProcessStartInfo Object or null if error occured</returns>
public static ProcessStartInfo CreateCMDDosCommandProcess(string DosCommand, bool bUseRunAs = false)
{
if (!String.IsNullOrEmpty(DosCommand))
{
//The "/C" Tells Windows to Run The Command then Terminate
string strCmdLine = "/C " + '\"' + DosCommand + '\"';
string WindowsSystem32Folder = System.Environment.GetFolderPath(Environment.SpecialFolder.System);
ProcessStartInfo startInfo = new ProcessStartInfo((WindowsSystem32Folder + "\\" + "CMD.exe"), strCmdLine);
//startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
if (bUseRunAs)
startInfo.Verb = "runas";
return startInfo;
}
return null;
}
}
}

274
Process/PStarter.cs Normal file
View File

@@ -0,0 +1,274 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
namespace Yaulw.Process
{
/// <remarks>
/// Used to Manage Launching/Killing Processes In an Application
/// </remarks>
public static class PStarter
{
#region Private Static Members
private static Dictionary<uint, String> _StartedProcesses = new Dictionary<uint, String>();
#endregion
#region Public Process Starter Methods
/// <summary>
/// Use this to call a DosCommand in a hidden command prompt and have the command return
/// you a value back, read from standard output
/// </summary>
/// <param name="processStart">processStartInfo</param>
/// <param name="bWait">true to wait till process ends, false otherwise</param>
/// <returns>the PID of the the newly started Process, or 0 if an error occured</returns>
public static string RunDosCommand(string DosCommand)
{
ProcessStartInfo processStart = PStartInfo.CreateCMDDosCommandProcess(DosCommand, true);
processStart.RedirectStandardOutput = true;
string output = String.Empty;
if ((processStart != null) && System.IO.File.Exists(processStart.FileName))
{
// Start the Process
try
{
System.Diagnostics.Process p1;
p1 = System.Diagnostics.Process.Start(processStart);
output = p1.StandardOutput.ReadToEnd();
p1.WaitForExit();
if (String.IsNullOrEmpty(output))
output = p1.StandardOutput.ReadToEnd();
}
catch (Exception e) { string msg = e.Message; /* ignore */ }
}
return output;
}
/// <summary>
/// Always Starts a New Process
/// </summary>
/// <param name="processStart">processStartInfo</param>
/// <param name="bWait">true to wait till process ends, false otherwise</param>
/// <param name="bMustBeUnique">true to check if the process of the same name has already been started, false otherwise</param>
/// <returns>the PID of the the newly started Process, or 0 if an error occured</returns>
//public static uint StartProcess(ProcessStartInfo processStart, bool bWait = false, bool bMustBeUnique = false)
public static uint StartProcess(ProcessStartInfo processStart, bool bWait, bool bMustBeUnique)
{
if ((processStart != null) && System.IO.File.Exists(processStart.FileName))
{
// Enforce Uniqueness * DISABLED * We can't ENFORCE UNIQUENESS WITHOUT ALSO INCLUDING COMMAND-LINE PARAMETERS
// ~TO DO SOMETIME LATER * DOESN"T MATTER HERE * ALREADY HANDLED BY CALLER ANYWAY *
//if (bMustBeUnique && ContainsProcessExe(processStart.FileName))
//{
// return 0;
//}
//else if (bMustBeUnique)
//{
// // Iterate the system's Processes's and make sure that the same process doesn't exist
// System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName(Path.GetFileNameWithoutExtension(processStart.FileName));
// foreach (System.Diagnostics.Process process in processes)
// {
// // Found, return 0
// if (String.Compare(process.MainModule.FileName, processStart.FileName, true) == 0)
// return 0;
// }
//}
// Start the Process
try
{
System.Diagnostics.Process p1;
p1 = System.Diagnostics.Process.Start(processStart);
// DISABLED
// Map if for later use
//_StartedProcesses.Add((uint)p1.Id, processStart.FileName.ToLower());
// Wait if asked
if (bWait)
p1.WaitForExit();
return (uint)p1.Id;
}
catch (Exception) { /* ignore */ }
}
return 0;
}
/// <summary>
/// Kills any process started thru PStarter, if it matches the Passed in PID
/// </summary>
/// <param name="PID">The Pid of the Process to Stop</param>
/// <param name="bMustBeHaveBeenStartedByUs">true to only shutdown a process that was started by PStarted</param>
/// <param name="CloseWaitTimeInSeconds">The time in Seconds to wait after closing the Process</param>
/// <param name="bTryClosingMainWindowFirst">true to try sending WM_CLOSE message to Window prior Killing Process</param>
/// <param name="MainWindowCloseWaitTimeInSeconds">The time in Seconds to wait after sending WM_CLOSE message for Process to Close * Only takes effect if bTryClosingMainWindowFirst is true *</param>
/// <returns>true if process stopped, false otherwise</returns>
//public static bool KillProcess(uint PID, bool bMustBeHaveBeenStartedByUs = false, uint CloseWaitTimeInSeconds = 1, bool bTryClosingMainWindowFirst = true, uint MainWindowCloseWaitTimeInSeconds = 2)
public static bool KillProcess(uint PID, bool bMustBeHaveBeenStartedByUs, uint CloseWaitTimeInSeconds, bool bTryClosingMainWindowFirst, uint MainWindowCloseWaitTimeInSeconds)
{
// Valid Process Id
bool bValidToClose = (PID != 0);
// Make sure that PStarted Started This Process
if (bValidToClose && bMustBeHaveBeenStartedByUs)
bValidToClose = _StartedProcesses.ContainsKey(PID);
// Is this process valid to close?
if (bValidToClose)
{
System.Diagnostics.Process p1 = null;
// Try getting the Process
try { p1 = System.Diagnostics.Process.GetProcessById((int)PID); }
catch (Exception) {/* ignore */}
// Process Found
if (p1 != null)
{
// If Main Window Exists, Try Closing this first
if (bTryClosingMainWindowFirst)
{
IntPtr hWnd = p1.MainWindowHandle;
if (hWnd == IntPtr.Zero)
{
// Try getting the window handle by Iterating TopLevel Windows
hWnd = Win32.Functions.GetFirstTopLevelWindowForProcess((int)PID);
}
// If we have a valid Window Handle, try closing it nicely
if (hWnd != IntPtr.Zero && Win32.User32.IsWindow(hWnd))
{
// Try the new school way && the old school way !!!
p1.CloseMainWindow();
Win32.User32.PostMessage(hWnd, (int)Win32.Definitions.WM.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
// Wait a little.. as specified by the configuration
System.Threading.Thread.Sleep((int)TimeSpan.FromSeconds(MainWindowCloseWaitTimeInSeconds).TotalMilliseconds);
// Retry getting the Process *Should be closed by now*
try { p1 = null; p1 = System.Diagnostics.Process.GetProcessById((int)PID); }
catch (Exception) {/* ignore */}
}
}
// Last Resort, Always try to Kill the Process
try { if (p1 != null) p1.Kill(); }
catch (Exception) { /* ignore */ }
// Wait a little
System.Threading.Thread.Sleep((int)TimeSpan.FromSeconds(CloseWaitTimeInSeconds).TotalMilliseconds);
// Retry getting the Process *Must be closed by now*
try { p1 = null; p1 = System.Diagnostics.Process.GetProcessById((int)PID); }
catch (Exception) {/* ignore */}
if (p1 == null)
{
// DISABLED
//_StartedProcesses.Remove(PID);
return true;
}
}
}
return false;
}
#endregion
#region Public Process Starter Helper Methods
/// <summary>
/// Retrieves the PIDs that were started using PStarter
/// </summary>
/// <returns>an uint[] array with Pids, or an empty array if none found</returns>
public static uint[] AllStartedProcessIDs()
{
// DISABLED
//List<uint> Pids = new List<uint>();
//foreach (int key in _StartedProcesses.Keys)
// Pids.Add((uint)key);
//return Pids.ToArray();
return null;
}
/// <summary>
/// Since when we start a Process and it can die/killed externally we wouldn't know,
/// PIDs #'s could be re-used by the OS, so we could accidentially kill a Process that isn't our own.
/// This functions allows a monitoring program to call in with currently running PIDs they know are good
/// on the running system, we can use these numbers and discard any PIDs internally that are no longer accurate
/// * This function will DELETE PIDs/Keys internally * call it only with is a complete list of all PIDs.
/// </summary>
/// <param name="currentlyRunningPIDs">an uint[] array with currently Running PIDs, that we can compare to our started PIDs</param>
public static void PerformGeneralCleanupOfAllStartedProcessIDs(uint[] currentlyRunningPIDs)
{
// DISABLED
//if ((currentlyRunningPIDs != null) && (currentlyRunningPIDs.Length > 0))
//{
// // Iterate thru the Internal DS and track any PID Keys that are no longer valid
// List<uint> RunningPidKeysToRemove = new List<uint>();
// foreach (uint key in _StartedProcesses.Keys)
// {
// if (!currentlyRunningPIDs.Contains(key))
// RunningPidKeysToRemove.Add(key);
// }
// // Remove * no longer valid * PID / Keys
// foreach (uint keyToRemove in RunningPidKeysToRemove)
// _StartedProcesses.Remove(keyToRemove);
//}
}
/// <summary>
/// Returns true if the ProcessExe was started with PStarter, False otherwise
/// </summary>
/// <param name="FileName">Process Executable Filename and Path</param>
/// <returns>true, if found, false otherwise</returns>
public static bool ContainsProcessExe(string FileName)
{
return _StartedProcesses.ContainsValue(FileName.ToLower());
}
/// <summary>
/// Get's the first PID that matches the Given Exe Process FileName
/// </summary>
/// <param name="FileName">Process Executable Filename and Path</param>
/// <returns>a Valid PID or 0 if not found</returns>
public static uint GetFirstPIDForProcessExe(string FileName)
{
if (ContainsProcessExe(FileName))
{
foreach (uint key in _StartedProcesses.Keys)
{
if (String.Compare(_StartedProcesses[key], FileName, true) == 0)
return key;
}
}
return 0;
}
/// <summary>
/// Get's all the PIDs that matches the Given Exe Process FileName
/// </summary>
/// <param name="FileName">Process Executable Filename and Path</param>
/// <returns>valid PIDs or empty PID array, if not found</returns>
public static uint[] GetPIDsForProcessExe(string FileName)
{
List<uint> foundProcess = new List<uint>();
if (ContainsProcessExe(FileName))
{
foreach (uint key in _StartedProcesses.Keys)
{
if (String.Compare(_StartedProcesses[key], FileName, true) == 0)
foundProcess.Add(key);
}
}
return foundProcess.ToArray();
}
#endregion
}
}

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
}
}

212
Process/ServiceW.cs Normal file
View File

@@ -0,0 +1,212 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceProcess;
using Yaulw.Win32;
using System.Runtime.InteropServices;
namespace Yaulw.Process
{
/// <remarks>
/// Wrapper Class around System.ServiceProcess's ServiceControl Class,
/// ~Little helper functions to make sure that we can safely interact with Services
/// </remarks>
public static class ServiceW
{
/// <summary>
/// Checks to see if the service exists on the local computer
/// </summary>
/// <param name="ServiceName">Name of Service to Check</param>
/// <returns>true if it exists, false otherwise</returns>
public static bool DoesServiceExist(string ServiceName)
{
try
{
ServiceController scm = new ServiceController(ServiceName);
if (scm != null && !String.IsNullOrEmpty(scm.ServiceName))
{
scm.Dispose();
return true;
}
}
catch (Exception) { /* ignore */ }
return false;
}
/// <summary>
/// Quick check to see if the service is running
/// </summary>
/// <param name="ServiceName">Name of Service to Check</param>
/// <returns>true if the service is running, false otherwise, if it doesn't exist returns true</returns>
public static bool IsServiceRunning(string ServiceName)
{
ServiceController scm = null;
try
{
scm = new ServiceController(ServiceName);
}
catch (Exception) { /* ignore */ }
if (scm != null)
{
bool bIsRunning = (scm.Status == ServiceControllerStatus.Running);
scm.Dispose();
return bIsRunning;
}
else
return false;
}
/// <summary>
/// Use this to Restart the Service
/// </summary>
/// <param name="ServiceName">Name of Service to Check</param>
/// <param name="bKillServiceByForceIfNeedBe">Set to true to try to force a Service Close by killing the Process, if the service is hanging</param>
/// <param name="WaitTimeoutInSeconds">Number of Seconds to wait for Service To Close/Start</param>
/// <param name="nStartupDelayInSeconds">Number of Seconds to wait inbetween closing and starting</param>
/// <returns>true if successful, false otherwise</returns>
public static bool RestartService(string ServiceName, bool bKillServiceByForceIfNeedBe = true, int WaitTimeoutInSeconds = 240, int nStartupDelayInSeconds = 2)
{
// Stop the Service
if (!StopService(ServiceName, bKillServiceByForceIfNeedBe, WaitTimeoutInSeconds))
return false;
// Delay Starting the Services for 'n' seconds
if (nStartupDelayInSeconds > 0)
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(nStartupDelayInSeconds));
// Start the Service
bool bIsStarted = StartService(ServiceName, WaitTimeoutInSeconds);
return bIsStarted;
}
/// <summary>
/// Use this to start a service
/// </summary>
/// <param name="ServiceName">Name of Service to Check</param>
/// <param name="WaitTimeoutInSeconds">Number of seconds to wait for Service to Start</param>
/// <returns>true if successful, false otherwise</returns>
public static bool StartService(string ServiceName, int WaitTimeoutInSeconds = 240)
{
ServiceController scm = null;
try
{
scm = new ServiceController(ServiceName);
// Wait for 'Stopped' State
if (scm.Status != ServiceControllerStatus.Running)
{
scm.Start();
if (WaitTimeoutInSeconds > 0)
scm.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(WaitTimeoutInSeconds));
}
}
catch (Exception) { /* ignore */ }
if (scm != null)
{
bool bSuccess = (scm.Status == ServiceControllerStatus.Running);
scm.Dispose();
return bSuccess;
}
else
return false;
}
/// <summary>
/// Use this to stop a service
/// </summary>
/// <param name="ServiceName">Name of Service to Check</param>
/// <param name="bKillServiceByForceIfNeedBe">Set to true to try to force a Service Close by killing the Process, if the service is hanging</param>
/// <param name="WaitTimeoutInSeconds">Number of seconds to wait for Service to Stop</param>
/// <returns>true if successful, false otherwise</returns>
public static bool StopService(string ServiceName, bool bKillServiceByForceIfNeedBe = true, int WaitTimeoutInSeconds = 240)
{
ServiceController scm = null;
try
{
scm = new ServiceController(ServiceName);
// Wait for 'Stopped' State
if (scm.Status != ServiceControllerStatus.Stopped)
{
scm.Stop();
if (WaitTimeoutInSeconds > 0)
scm.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(WaitTimeoutInSeconds));
}
}
catch (Exception) { /* ignore */ }
try
{
if (scm != null)
{
bool bSuccess = (scm.Status == ServiceControllerStatus.Stopped);
// Always try Killing Service By Force, even if bSuccess is true,
// just to try to guarantee that the service is dead for good
if (bKillServiceByForceIfNeedBe)
bSuccess = StopServiceByForce(scm) || bSuccess;
scm.Dispose();
return bSuccess;
}
else
return false;
}
catch (Exception) { /* ignore */ }
return false;
}
/// <summary>
/// Brutal way to stop a service * Not Recommended *,
/// according to article:
/// </summary>
/// <see cref="http://community.bartdesmet.net/blogs/bart/archive/2004/10/16/438.aspx"/>
/// <see cref="http://stackoverflow.com/questions/884853/service-not-fully-stopped-after-servicecontroller-stop"/>
/// <param name="scm">a Service Controller Object whose PID you would like to kill</param>
/// <returns>true if successfull, false otherwise</returns>
private static bool StopServiceByForce(ServiceController scm)
{
Structures.SERVICE_STATUS_PROCESS ssp = new Structures.SERVICE_STATUS_PROCESS();
int ignored;
try
{
// Obtain information about the service, and specifically its hosting process,
// from the Service Control Manager.
if (!Advapi32.QueryServiceStatusEx(scm.ServiceHandle.DangerousGetHandle(), Definitions.SC_STATUS_PROCESS_INFO, ref ssp, Marshal.SizeOf(ssp), out ignored))
{
//throw new Exception("Couldn't obtain service process information.");
return false;
}
// A few quick sanity checks that what the caller wants is *possible*.
if (ssp.dwServiceType != Definitions.SERVICE_WIN32_OWN_PROCESS)
{
//throw new Exception("Can't wait for the service's hosting process to exit because there may be multiple services in the process (dwServiceType is not SERVICE_WIN32_OWN_PROCESS");
return false;
}
if ((ssp.dwServiceFlags & Definitions.SERVICE_RUNS_IN_SYSTEM_PROCESS) != 0)
{
//throw new Exception("Can't wait for the service's hosting process to exit because the hosting process is a critical system process that will not exit (SERVICE_RUNS_IN_SYSTEM_PROCESS flag set)");
return false;
}
if (ssp.dwProcessId == 0)
{
//throw new Exception("Can't wait for the service's hosting process to exit because the process ID is not known.");
return false;
}
// Try closing the Process Manually
bool bCloseSuccess = PStarter.KillProcess((uint)ssp.dwProcessId, false, 1, false, 2);
return bCloseSuccess;
}
catch (Exception) { /* ignore */ }
return false;
}
}
}