SEBWIN-301, SEBWIN-322: Improved service feature configuration with retry mechanism.
This commit is contained in:
parent
18e6b366a5
commit
d54d7c17dc
1 changed files with 64 additions and 33 deletions
|
@ -18,7 +18,9 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
[Serializable]
|
[Serializable]
|
||||||
internal abstract class ServiceConfiguration : FeatureConfiguration
|
internal abstract class ServiceConfiguration : FeatureConfiguration
|
||||||
{
|
{
|
||||||
private static readonly TimeSpan TEN_SECONDS = TimeSpan.FromSeconds(10);
|
private static readonly TimeSpan FIVE_SECONDS = TimeSpan.FromSeconds(5);
|
||||||
|
private const int MAX_ATTEMPTS = 5;
|
||||||
|
|
||||||
private IList<ServiceDataItem> originalItems;
|
private IList<ServiceDataItem> originalItems;
|
||||||
|
|
||||||
protected abstract IEnumerable<ServiceConfigurationItem> Items { get; }
|
protected abstract IEnumerable<ServiceConfigurationItem> Items { get; }
|
||||||
|
@ -34,7 +36,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
|
|
||||||
foreach (var item in Items)
|
foreach (var item in Items)
|
||||||
{
|
{
|
||||||
success &= TrySet(new ServiceDataItem { Name = item.Name, Status = item.Disabled });
|
success &= TrySetWithRetry(new ServiceDataItem { Name = item.Name, Status = item.Disabled });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
|
@ -55,7 +57,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
|
|
||||||
foreach (var item in Items)
|
foreach (var item in Items)
|
||||||
{
|
{
|
||||||
success &= TrySet(new ServiceDataItem { Name = item.Name, Status = item.Enabled });
|
success &= TrySetWithRetry(new ServiceDataItem { Name = item.Name, Status = item.Enabled });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
|
@ -114,7 +116,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
{
|
{
|
||||||
foreach (var item in new List<ServiceDataItem>(originalItems))
|
foreach (var item in new List<ServiceDataItem>(originalItems))
|
||||||
{
|
{
|
||||||
if (TrySet(item))
|
if (TrySetWithRetry(item))
|
||||||
{
|
{
|
||||||
originalItems.Remove(item);
|
originalItems.Remove(item);
|
||||||
}
|
}
|
||||||
|
@ -153,38 +155,56 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TrySetWithRetry(ServiceDataItem item)
|
||||||
|
{
|
||||||
|
var success = false;
|
||||||
|
|
||||||
|
if (IsAvailable(item))
|
||||||
|
{
|
||||||
|
for (var attempt = 1; attempt <= MAX_ATTEMPTS && !success; attempt++)
|
||||||
|
{
|
||||||
|
logger.Debug($"Attempt {attempt}/{MAX_ATTEMPTS} to set service {item}...");
|
||||||
|
success = TrySet(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
logger.Error($"All attempts to set service {item} have failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Warn($"Cannot set service {item} as it does not exist!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
private bool TrySet(ServiceDataItem item)
|
private bool TrySet(ServiceDataItem item)
|
||||||
{
|
{
|
||||||
var success = false;
|
var success = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (IsAvailable(item))
|
using (var service = new ServiceController(item.Name))
|
||||||
{
|
{
|
||||||
using (var service = new ServiceController(item.Name))
|
if (item.Status == ServiceStatus.Running)
|
||||||
{
|
{
|
||||||
if (item.Status == ServiceStatus.Running)
|
success = TryStart(service);
|
||||||
{
|
}
|
||||||
success = TryStart(service);
|
else if (item.Status == ServiceStatus.Stopped)
|
||||||
}
|
{
|
||||||
else if (item.Status == ServiceStatus.Stopped)
|
success = TryStop(service);
|
||||||
{
|
}
|
||||||
success = TryStop(service);
|
|
||||||
}
|
if (success)
|
||||||
|
{
|
||||||
if (success)
|
logger.Debug($"Successfully set service {item}.");
|
||||||
{
|
}
|
||||||
logger.Debug($"Successfully set service {item}.");
|
else
|
||||||
}
|
{
|
||||||
else
|
logger.Warn($"Could not set service {item}! Current status: {service.Status}.");
|
||||||
{
|
|
||||||
logger.Warn($"Could not set service {item}! Current status: {service.Status}.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.Warn($"Cannot set service {item} as it does not exist!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -197,11 +217,11 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
|
|
||||||
private bool TryStart(ServiceController service)
|
private bool TryStart(ServiceController service)
|
||||||
{
|
{
|
||||||
var success = true;
|
var success = false;
|
||||||
|
|
||||||
if (service.Status == ServiceControllerStatus.PausePending)
|
if (service.Status == ServiceControllerStatus.PausePending)
|
||||||
{
|
{
|
||||||
service.WaitForStatus(ServiceControllerStatus.Paused, TEN_SECONDS);
|
service.WaitForStatus(ServiceControllerStatus.Paused, FIVE_SECONDS);
|
||||||
service.Refresh();
|
service.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +239,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
|
|
||||||
if (service.Status == ServiceControllerStatus.StartPending || service.Status == ServiceControllerStatus.ContinuePending)
|
if (service.Status == ServiceControllerStatus.StartPending || service.Status == ServiceControllerStatus.ContinuePending)
|
||||||
{
|
{
|
||||||
service.WaitForStatus(ServiceControllerStatus.Running, TEN_SECONDS);
|
service.WaitForStatus(ServiceControllerStatus.Running, FIVE_SECONDS);
|
||||||
service.Refresh();
|
service.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +263,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
|
|
||||||
if (service.Status == ServiceControllerStatus.StartPending || service.Status == ServiceControllerStatus.ContinuePending)
|
if (service.Status == ServiceControllerStatus.StartPending || service.Status == ServiceControllerStatus.ContinuePending)
|
||||||
{
|
{
|
||||||
service.WaitForStatus(ServiceControllerStatus.Running, TEN_SECONDS);
|
service.WaitForStatus(ServiceControllerStatus.Running, FIVE_SECONDS);
|
||||||
service.Refresh();
|
service.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +275,7 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
|
|
||||||
if (service.Status == ServiceControllerStatus.StopPending)
|
if (service.Status == ServiceControllerStatus.StopPending)
|
||||||
{
|
{
|
||||||
service.WaitForStatus(ServiceControllerStatus.Stopped, TEN_SECONDS);
|
service.WaitForStatus(ServiceControllerStatus.Stopped, FIVE_SECONDS);
|
||||||
service.Refresh();
|
service.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +289,18 @@ namespace SafeExamBrowser.Lockdown.FeatureConfigurations.ServiceConfigurations
|
||||||
|
|
||||||
private bool IsAvailable(ServiceDataItem item)
|
private bool IsAvailable(ServiceDataItem item)
|
||||||
{
|
{
|
||||||
return ServiceController.GetServices().Any(s => s.ServiceName == item.Name);
|
var available = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
available = ServiceController.GetServices().Any(s => s.ServiceName == item.Name);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error($"Failed to check whether service '{item.Name}' is available!", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return available;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceStatus ToStatus(ServiceControllerStatus status)
|
private ServiceStatus ToStatus(ServiceControllerStatus status)
|
||||||
|
|
Loading…
Reference in a new issue