213 lines
8.8 KiB
C#
213 lines
8.8 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|