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
{
///
/// Wrapper Class around System.ServiceProcess's ServiceControl Class,
/// ~Little helper functions to make sure that we can safely interact with Services
///
public static class ServiceW
{
///
/// Checks to see if the service exists on the local computer
///
/// Name of Service to Check
/// true if it exists, false otherwise
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;
}
///
/// Quick check to see if the service is running
///
/// Name of Service to Check
/// true if the service is running, false otherwise, if it doesn't exist returns true
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;
}
///
/// Use this to Restart the Service
///
/// Name of Service to Check
/// Set to true to try to force a Service Close by killing the Process, if the service is hanging
/// Number of Seconds to wait for Service To Close/Start
/// Number of Seconds to wait inbetween closing and starting
/// true if successful, false otherwise
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;
}
///
/// Use this to start a service
///
/// Name of Service to Check
/// Number of seconds to wait for Service to Start
/// true if successful, false otherwise
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;
}
///
/// Use this to stop a service
///
/// Name of Service to Check
/// Set to true to try to force a Service Close by killing the Process, if the service is hanging
/// Number of seconds to wait for Service to Stop
/// true if successful, false otherwise
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;
}
///
/// Brutal way to stop a service * Not Recommended *,
/// according to article:
///
///
///
/// a Service Controller Object whose PID you would like to kill
/// true if successfull, false otherwise
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;
}
}
}