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