/// <summary> /// Block until a service stops, is killed, or is found to be already dead. /// </summary> /// <param name="serviceName">The name of the service you would like to wait for.</param> /// <param name="timeout">An amount of time you would like to wait for. uint.MaxValue is the default, and it will force this thread to wait indefinitely.</param> public static void WaitForServiceToStop(string serviceName, uint timeout = uint.MaxValue) { // Ensure that this thread's identity is mapped, 1-to-1, with a native OS thread. Thread.BeginThreadAffinity(); GCHandle notifyHandle = default(GCHandle); StatusChangedCallbackDelegate changeDelegate = ReceivedStatusChangedEvent; IntPtr hSCM = IntPtr.Zero; IntPtr hService = IntPtr.Zero; try { hSCM = OpenSCManager(null, null, (uint)0xF003F); if (hSCM != IntPtr.Zero) { hService = OpenService(hSCM, serviceName, (uint)0xF003F); if (hService != IntPtr.Zero) { SERVICE_NOTIFY notify = new SERVICE_NOTIFY(); notify.dwVersion = 2; notify.pfnNotifyCallback = Marshal.GetFunctionPointerForDelegate(changeDelegate); notify.ServiceStatus = new SERVICE_STATUS_PROCESS(); notifyHandle = GCHandle.Alloc(notify, GCHandleType.Pinned); IntPtr pinnedNotifyStructure = notifyHandle.AddrOfPinnedObject(); NotifyServiceStatusChange(hService, (uint)0x00000001, pinnedNotifyStructure); SleepEx(timeout, true); } } } finally { // Clean up at the end of our operation, or if this thread is aborted. if (hService != IntPtr.Zero) { CloseServiceHandle(hService); } if (hSCM != IntPtr.Zero) { CloseServiceHandle(hSCM); } GC.KeepAlive(changeDelegate); if (notifyHandle != default(GCHandle)) { notifyHandle.Free(); } Thread.EndThreadAffinity(); } }
/// <summary> /// Block until a service stops or is found to be already dead. /// </summary> /// <param name="serviceName">The name of the service you would like to wait for.</param> public static void WaitForServiceToStop(string serviceName) { IntPtr hSCM = OpenSCManager(null, null, (uint)0xF003F); if (hSCM != IntPtr.Zero) { IntPtr hService = OpenService(hSCM, serviceName, (uint)0xF003F); if (hService != IntPtr.Zero) { StatusChangedCallbackDelegate changeDelegate = ReceivedStatusChangedEvent; SERVICE_NOTIFY notify = new SERVICE_NOTIFY(); notify.dwVersion = 2; notify.pfnNotifyCallback = Marshal.GetFunctionPointerForDelegate(changeDelegate); notify.ServiceStatus = new SERVICE_STATUS_PROCESS(); GCHandle notifyHandle = GCHandle.Alloc(notify, GCHandleType.Pinned); IntPtr unmanagedNotifyStructure = notifyHandle.AddrOfPinnedObject(); NotifyServiceStatusChange(hService, (uint)0x00000001, unmanagedNotifyStructure); SleepEx(uint.MaxValue, true); notifyHandle.Free(); CloseServiceHandle(hService); } CloseServiceHandle(hSCM); } }