using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.ServiceProcess; namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.TestSupport.Probes; /// /// Queries the Windows Service Control Manager to report whether a named service is /// installed, its current state, and its start type. Non-Windows hosts return Skip. /// public static class ServiceProbe { public static PrerequisiteCheck Check( string serviceName, PrerequisiteCategory category, bool hardRequired, string whatItDoes) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return new PrerequisiteCheck( Name: $"service:{serviceName}", Category: category, Status: PrerequisiteStatus.Skip, Detail: "Service probes only run on Windows."); } return CheckWindows(serviceName, category, hardRequired, whatItDoes); } [SupportedOSPlatform("windows")] private static PrerequisiteCheck CheckWindows( string serviceName, PrerequisiteCategory category, bool hardRequired, string whatItDoes) { try { using var sc = new ServiceController(serviceName); // Touch the Status to force the SCM lookup; if the service doesn't exist, this throws // InvalidOperationException with message "Service ... was not found on computer.". var status = sc.Status; var startType = sc.StartType; return status switch { ServiceControllerStatus.Running => new PrerequisiteCheck( $"service:{serviceName}", category, PrerequisiteStatus.Pass, $"Running ({whatItDoes})"), // DemandStart services (like NmxSvc) that are Stopped are not necessarily a // failure — the master service (aaBootstrap) brings them up on demand. Treat // Stopped+Demand as Warn so operators know the situation but tests still proceed. ServiceControllerStatus.Stopped when startType == ServiceStartMode.Manual => new PrerequisiteCheck( $"service:{serviceName}", category, PrerequisiteStatus.Warn, $"Installed but Stopped (start type Manual — {whatItDoes}). " + "Will be pulled up on demand by the master service; fine for tests."), ServiceControllerStatus.Stopped => Fail( $"Installed but Stopped. Start with: sc.exe start {serviceName} ({whatItDoes})"), _ => new PrerequisiteCheck( $"service:{serviceName}", category, PrerequisiteStatus.Warn, $"Transitional state {status} ({whatItDoes}) — try again in a few seconds."), }; PrerequisiteCheck Fail(string detail) => new( $"service:{serviceName}", category, hardRequired ? PrerequisiteStatus.Fail : PrerequisiteStatus.Warn, detail); } catch (InvalidOperationException ex) when (ex.Message.Contains("was not found", StringComparison.OrdinalIgnoreCase)) { return new PrerequisiteCheck( $"service:{serviceName}", category, hardRequired ? PrerequisiteStatus.Fail : PrerequisiteStatus.Warn, $"Not installed ({whatItDoes}). Install the relevant System Platform component and retry."); } catch (Exception ex) { return new PrerequisiteCheck( $"service:{serviceName}", category, PrerequisiteStatus.Warn, $"Probe failed ({ex.GetType().Name}: {ex.Message}) — treat as unknown."); } } }