public static void ServiceStatusChanged(IntPtr parameter) { try { WinApi.Advapi32.SERVICE_NOTIFY n = Marshal.PtrToStructure <WinApi.Advapi32.SERVICE_NOTIFY>(parameter); //Log.Main.Trace("Service status: " + n.ServiceStatus.dwCurrentState); if (serviceStatus == n.ServiceStatus.dwCurrentState)//on some Windows ServiceStatusChanged is invoked many times! { return; } serviceStatus = n.ServiceStatus.dwCurrentState; ServiceControllerStatus status; switch (n.ServiceStatus.dwCurrentState) { case 1: //stopped status = ServiceControllerStatus.Stopped; _this = null; break; case 4: //running status = ServiceControllerStatus.Running; lock (instanceContext) { _this?.Unsubscribe(); _this?.Close(); _this = new CisteraScreenCaptureService.UiApiClient(instanceContext); _this.Subscribe(); //beginKeepAliveServiceConnection();//it seems to be redundant because of infinite timeout, but sometimes the channel gets closed due to errors } break; default: throw new Exception("Unknown option: " + n.ServiceStatus.dwCurrentState); } Log.Main.Inform("Service status: " + status); SysTray.This.ServiceStateChanged(status); } catch (Exception e) { Log.Main.Error(e); } finally { serviceStatusChangedManualResetEvent.Set(); } }
static void beginMonitorServiceStartStop() { try { IntPtr hSCM = WinApi.Advapi32.OpenSCManager(null, null, WinApi.Advapi32.SCM_ACCESS.SC_MANAGER_CONNECT);//(WinApi.Advapi32.SCM_ACCESS)0xF003F);// if (hSCM == IntPtr.Zero) { throw new Exception("OpenSCManager: " + ErrorRoutines.GetLastError()); } IntPtr hService = WinApi.Advapi32.OpenService(hSCM, Cliver.CisteraScreenCaptureService.Program.SERVICE_NAME, WinApi.Advapi32.OpenServiceDesiredAccess.SERVICE_QUERY_STATUS); if (hService == IntPtr.Zero) { throw new Exception("OpenService: " + ErrorRoutines.GetLastError()); } ThreadRoutines.StartTry(() => { for (; ;) { serviceSatusChangedNotify = new WinApi.Advapi32.SERVICE_NOTIFY(); serviceSatusChangedNotify.dwVersion = 2; serviceSatusChangedNotify.pfnNotifyCallback = Marshal.GetFunctionPointerForDelegate(serviceStatusChangedDelegate); serviceSatusChangedNotify.pContext = IntPtr.Zero; serviceSatusChangedNotify.dwNotificationStatus = 0; WinApi.Advapi32.SERVICE_STATUS_PROCESS process; process.dwServiceType = 0; process.dwCurrentState = 0; process.dwControlsAccepted = 0; process.dwWin32ExitCode = 0; process.dwServiceSpecificExitCode = 0; process.dwCheckPoint = 0; process.dwWaitHint = 0; process.dwProcessId = 0; process.dwServiceFlags = 0; serviceSatusChangedNotify.ServiceStatus = process; serviceSatusChangedNotify.dwNotificationTriggered = 0; serviceSatusChangedNotify.pszServiceNames = Marshal.StringToHGlobalUni(Cliver.CisteraScreenCaptureService.Program.SERVICE_NAME); notifyHandle = GCHandle.Alloc(serviceSatusChangedNotify, GCHandleType.Pinned); unmanagedNotifyStructure = notifyHandle.AddrOfPinnedObject(); if (0 != WinApi.Advapi32.NotifyServiceStatusChange(hService, WinApi.Advapi32.NotifyMask.SERVICE_NOTIFY_RUNNING | WinApi.Advapi32.NotifyMask.SERVICE_NOTIFY_STOPPED, unmanagedNotifyStructure)) { LogMessage.Error("NotifyServiceStatusChange: " + ErrorRoutines.GetLastError()); } serviceStatusChangedManualResetEvent.Reset(); serviceStatusChangedManualResetEvent.WaitOne(); notifyHandle.Free(); } }, null, () => { try { notifyHandle.Free(); } catch { } } ); } catch (Exception e) { LogMessage.Error(e); } }