public void NotifyServiceStatusChangeTest() { var cnt = 0; ManualResetEvent evt; Thread.BeginThreadAffinity(); try { PFN_SC_NOTIFY_CALLBACK callback = ChangeDelegate; var svcNotify = new SERVICE_NOTIFY_2 { dwVersion = 2, pfnNotifyCallback = Marshal.GetFunctionPointerForDelegate(callback), }; using (evt = new ManualResetEvent(false)) using (var pNotify = new PinnedObject(svcNotify)) { Assert.That(NotifyServiceStatusChange(hSvc, SERVICE_NOTIFY_FLAGS.SERVICE_NOTIFY_PAUSED | SERVICE_NOTIFY_FLAGS.SERVICE_NOTIFY_PAUSE_PENDING | SERVICE_NOTIFY_FLAGS.SERVICE_NOTIFY_CONTINUE_PENDING, pNotify), ResultIs.Successful); var th = new Thread(ThreadExec); th.Start((SC_HANDLE)hSvc); while (!evt.WaitOne(5)) { ; } Assert.That(cnt, Is.GreaterThan(0)); } } finally { Thread.EndThreadAffinity(); } void ChangeDelegate(IntPtr pParameter) { System.Diagnostics.Debug.WriteLine(pParameter.ToStructure <SERVICE_NOTIFY_2>().ServiceStatus.dwCurrentState); cnt++; } void ThreadExec(object handle) { var svc = (SC_HANDLE)handle; System.Diagnostics.Debug.WriteLine("Pausing..."); if (!ControlService(svc, ServiceControl.SERVICE_CONTROL_PAUSE, out _)) { System.Diagnostics.Debug.WriteLine($"Pausing failed: {Win32Error.GetLastError()}"); } WaitForServiceStatus(svc, ServiceState.SERVICE_PAUSED); System.Diagnostics.Debug.WriteLine("Continuing..."); if (!ControlService(svc, ServiceControl.SERVICE_CONTROL_CONTINUE, out _)) { System.Diagnostics.Debug.WriteLine($"Pausing failed: {Win32Error.GetLastError()}"); } WaitForServiceStatus(svc, ServiceState.SERVICE_RUNNING); System.Diagnostics.Debug.WriteLine("Running..."); evt.Set(); } }
public void NotifyServiceStatusChangeTest() { var svcNotify = new SERVICE_NOTIFY_2 { dwVersion = 2, pfnNotifyCallback = ChangeDelegate }; Thread.BeginThreadAffinity(); var ret = NotifyServiceStatusChange(hSvc, SERVICE_NOTIFY_FLAGS.SERVICE_NOTIFY_PAUSED | SERVICE_NOTIFY_FLAGS.SERVICE_NOTIFY_PAUSE_PENDING | SERVICE_NOTIFY_FLAGS.SERVICE_NOTIFY_CONTINUE_PENDING, ref svcNotify); if (ret.Failed) { TestContext.WriteLine(ret); } Assert.That(ret.Succeeded, Is.True); new Thread(ThreadExec).Start(); Kernel32.SleepEx(10000, true); Thread.EndThreadAffinity(); void ChangeDelegate(ref SERVICE_NOTIFY_2 pParameter) { TestContext.WriteLine(pParameter.ServiceStatus.dwCurrentState); } void ThreadExec() { using (var mgr = OpenSCManager(null, null, ScManagerAccessTypes.SC_MANAGER_ALL_ACCESS)) { if (!mgr.IsInvalid) { using (var svc = OpenService(hSvcMgr, svcName, ServiceAccessTypes.SERVICE_ALL_ACCESS)) { if (!svc.IsInvalid) { TestContext.WriteLine("Pausing..."); ControlService(svc, ServiceControl.SERVICE_CONTROL_PAUSE, out _); Thread.Sleep(3000); TestContext.WriteLine("Continuing..."); ControlService(svc, ServiceControl.SERVICE_CONTROL_CONTINUE, out _); Thread.Sleep(3000); } } } } } }