initial checkin of yaulw (locally)
This commit is contained in:
274
Process/PStarter.cs
Normal file
274
Process/PStarter.cs
Normal 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user