}
/// <summary>
- /// A set of services on which the given service object is depend upon.
+ /// A set of services on which the given service object is dependent upon.
/// </summary>
public unsafe ServiceController[] ServicesDependedOn
{
public void LogWritten()
{
string serviceName = Guid.NewGuid().ToString();
- // If the username is null, then the service is created under LocalSystem Account which have access to EventLog.
+ // If the username is null, then the service is created under LocalSystem Account which has access to EventLog.
var testService = new TestServiceProvider(serviceName);
Assert.True(EventLog.SourceExists(serviceName));
testService.DeleteTestServices();
[ConditionalFact(nameof(IsProcessElevated))]
public void Dependencies()
{
- // The test service creates a number of dependent services, each of which is depended on
- // by all the services created after it.
var controller = new ServiceController(_testService.TestServiceName);
Assert.Equal(0, controller.DependentServices.Length);
Assert.Equal(1, controller.ServicesDependedOn.Length);
- var dependentController = new ServiceController(_testService.TestServiceName + ".Dependent");
- Assert.Equal(1, dependentController.DependentServices.Length);
- Assert.Equal(0, dependentController.ServicesDependedOn.Length);
+ var prerequisiteServiceController = new ServiceController(_testService.TestServiceName + ".Prerequisite");
+ Assert.Equal(1, prerequisiteServiceController.DependentServices.Length);
+ Assert.Equal(0, prerequisiteServiceController.ServicesDependedOn.Length);
- Assert.Equal(controller.ServicesDependedOn[0].ServiceName, dependentController.ServiceName);
- Assert.Equal(dependentController.DependentServices[0].ServiceName, controller.ServiceName);
+ Assert.Equal(controller.ServicesDependedOn[0].ServiceName, prerequisiteServiceController.ServiceName);
+ Assert.Equal(prerequisiteServiceController.DependentServices[0].ServiceName, controller.ServiceName);
}
[ConditionalFact(nameof(IsProcessElevated))]
var controller = new ServiceController(_testService.TestServiceName);
Assert.Equal(ServiceStartMode.Manual, controller.StartType);
- // Check for the startType of the dependent services.
+ // Check for the startType of the services that depend on the test service
for (int i = 0; i < controller.DependentServices.Length; i++)
{
Assert.Equal(ServiceStartMode.Disabled, controller.DependentServices[i].StartType);
public void Stop_FalseArg_WithDependentServices_ThrowsInvalidOperationException()
{
var controller = new ServiceController(_testService.TestServiceName);
- controller.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
- Assert.Throws<InvalidOperationException>(() => controller.Stop(stopDependentServices: false));
+ Assert.Equal(0, controller.DependentServices.Length);
+ Assert.Equal(1, controller.ServicesDependedOn.Length);
+
+ var prerequisiteServiceController = new ServiceController(_testService.TestServiceName + ".Prerequisite");
+ Assert.Equal(1, prerequisiteServiceController.DependentServices.Length);
+ Assert.Equal(0, prerequisiteServiceController.ServicesDependedOn.Length);
+
+ prerequisiteServiceController.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
+ Assert.Throws<InvalidOperationException>(() => prerequisiteServiceController.Stop(stopDependentServices: false));
}
[ConditionalFact(nameof(IsProcessElevated))]
var controller = new ServiceController(_testService.TestServiceName);
controller.WaitForStatus(ServiceControllerStatus.Running, _testService.ControlTimeout);
+ // stop the services that depend on this service
foreach (var dependentService in controller.DependentServices)
{
dependentService.Stop(stopDependentServices: false);
// To view tracing, use DbgView from sysinternals.com;
// run it elevated, check "Capture>Global Win32" and "Capture>Win32",
// and filter to just messages beginning with "##"
- internal const bool DebugTracing = false;
+ internal const bool DebugTracing = false; // toggle in TestServiceProvider.cs as well
private bool _disposed;
private Task _waitClientConnect;
public string ServiceCommandLine { get; set; }
+ // Install and start the test service, after starting any prerequisite services it depends on
public unsafe void Install()
{
string username = Username;
}
// Build servicesDependedOn string
+ // These are prerequisite services that must be started before this service
string servicesDependedOn = null;
if (ServicesDependedOn.Length > 0)
{
if (serviceManagerHandle.IsInvalid)
throw new InvalidOperationException("Cannot open Service Control Manager");
+ TestService.DebugTrace($"TestServiceInstaller: creating service {ServiceName} with prerequisite services {servicesDependedOn}");
+
// Install the service
using (var serviceHandle = new SafeServiceHandle(Interop.Advapi32.CreateService(serviceManagerHandle, ServiceName,
DisplayName, Interop.Advapi32.ServiceAccessOptions.ACCESS_TYPE_ALL, Interop.Advapi32.ServiceTypeOptions.SERVICE_TYPE_WIN32_OWN_PROCESS,
{
if (svc.Status != ServiceControllerStatus.Running)
{
- TestService.DebugTrace("TestServiceInstaller: instructing ServiceController to Start service " + ServiceName);
+ TestService.DebugTrace($"TestServiceInstaller: instructing ServiceController to start service {ServiceName}");
svc.Start();
if (!ServiceName.StartsWith("PropagateExceptionFromOnStart"))
svc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(120));
}
+ else
+ {
+ TestService.DebugTrace("TestServiceInstaller: service {ServiceName} already running");
+ }
}
}
}
// To view tracing, use DbgView from sysinternals.com;
// run it elevated, check "Capture>Global Win32" and "Capture>Win32",
// and filter to just messages beginning with "##"
- internal const bool DebugTracing = false;
+ internal const bool DebugTracing = false; // toggle in TestService.cs as well
private const int readTimeout = 60000;
public readonly string TestServiceName;
public readonly string TestServiceDisplayName;
- private readonly TestServiceProvider _dependentServices;
+ private readonly TestServiceProvider _prerequisiteServices;
+
+ // Creates a test service with a prerequisite service
public TestServiceProvider()
{
TestMachineName = ".";
TestServiceName = Guid.NewGuid().ToString();
TestServiceDisplayName = "Test Service " + TestServiceName;
- _dependentServices = new TestServiceProvider(TestServiceName + ".Dependent");
+ _prerequisiteServices = new TestServiceProvider(TestServiceName + ".Prerequisite");
// Create the service
CreateTestServices();
}
+ // Creates a test service with no prerequisite services
public TestServiceProvider(string serviceName)
{
TestMachineName = ".";
ControlTimeout = TimeSpan.FromSeconds(120);
TestServiceName = serviceName;
TestServiceDisplayName = "Test Service " + TestServiceName;
-
+
// Create the service
CreateTestServices();
}
private void CreateTestServices()
{
+ DebugTrace($"TestServiceProvider: Creating test service {TestServiceName}");
TestServiceInstaller testServiceInstaller = new TestServiceInstaller();
testServiceInstaller.ServiceName = TestServiceName;
testServiceInstaller.Description = "__Dummy Test Service__";
testServiceInstaller.Username = null;
- if (_dependentServices != null)
+ if (_prerequisiteServices != null)
{
- testServiceInstaller.ServicesDependedOn = new string[] { _dependentServices.TestServiceName };
+ DebugTrace($"TestServiceProvider: .. with prequisite services {_prerequisiteServices.TestServiceName}");
+ testServiceInstaller.ServicesDependedOn = new string[] { _prerequisiteServices.TestServiceName };
}
string processName = Process.GetCurrentProcess().MainModule.FileName;
}
testServiceInstaller.ServiceCommandLine = $"\"{processName}\" {arguments}";
-
+ DebugTrace($"TestServiceProvider: Executing {testServiceInstaller.ServiceCommandLine}");
testServiceInstaller.Install();
+ DebugTrace("TestServiceProvider: Completed install of test service");
}
public void DeleteTestServices()
TestServiceInstaller testServiceInstaller = new TestServiceInstaller();
testServiceInstaller.ServiceName = TestServiceName;
testServiceInstaller.RemoveService();
+ DebugTrace("TestServiceProvider: Removed test service");
}
finally
{
- // Lets be sure to try and clean up dependenct services even if something goes
+ // Lets be sure to try and clean up prerequisite services even if something goes
// wrong with the full removal of the other service.
- if (_dependentServices != null)
+ if (_prerequisiteServices != null)
{
- _dependentServices.DeleteTestServices();
+ _prerequisiteServices.DeleteTestServices();
+ DebugTrace("TestServiceProvider: Deleted test services");
}
}
}