diff --git a/NzbDrone.Common.Test/ServiceProviderTests.cs b/NzbDrone.Common.Test/ServiceProviderTests.cs index b5b1874d4..716cc7f0f 100644 --- a/NzbDrone.Common.Test/ServiceProviderTests.cs +++ b/NzbDrone.Common.Test/ServiceProviderTests.cs @@ -1,4 +1,5 @@ -using System.ServiceProcess; +using System; +using System.ServiceProcess; using FluentAssertions; using NUnit.Framework; using NzbDrone.Test.Common; @@ -16,23 +17,28 @@ public class ServiceProviderTests : TestBase public void Setup() { WindowsOnly(); - - - if (Subject.ServiceExist(TEMP_SERVICE_NAME)) - { - Subject.UnInstall(TEMP_SERVICE_NAME); - } + CleanupService(); } [TearDown] public void TearDown() { WindowsOnly(); + CleanupService(); + } + + private void CleanupService() + { if (Subject.ServiceExist(TEMP_SERVICE_NAME)) { Subject.UnInstall(TEMP_SERVICE_NAME); } + + if (Subject.IsServiceRunning(ALWAYS_INSTALLED_SERVICE)) + { + Subject.Stop(ALWAYS_INSTALLED_SERVICE); + } } [Test] @@ -86,6 +92,19 @@ public void Should_be_able_to_start_and_stop_service() .Should().Be(ServiceControllerStatus.Stopped); } + [Test] + public void should_throw_if_starting_a_running_serivce() + { + Subject.GetService(ALWAYS_INSTALLED_SERVICE).Status + .Should().NotBe(ServiceControllerStatus.Running); + + Subject.Start(ALWAYS_INSTALLED_SERVICE); + Assert.Throws(() => Subject.Start(ALWAYS_INSTALLED_SERVICE)); + + + ExceptionVerification.ExpectedWarns(1); + } + [Test] public void Should_log_warn_if_on_stop_if_service_is_already_stopped() { diff --git a/NzbDrone.Common/IDiskProvider.cs b/NzbDrone.Common/DiskProvider.cs similarity index 100% rename from NzbDrone.Common/IDiskProvider.cs rename to NzbDrone.Common/DiskProvider.cs diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index 7d3ed29ea..c18a6f6b4 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -148,14 +148,14 @@ - + - + - + diff --git a/NzbDrone.Common/IProcessProvider.cs b/NzbDrone.Common/ProcessProvider.cs similarity index 85% rename from NzbDrone.Common/IProcessProvider.cs rename to NzbDrone.Common/ProcessProvider.cs index c10bf6af0..4409d1ba4 100644 --- a/NzbDrone.Common/IProcessProvider.cs +++ b/NzbDrone.Common/ProcessProvider.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using NLog; @@ -12,10 +11,9 @@ public interface IProcessProvider ProcessInfo GetCurrentProcess(); ProcessInfo GetProcessById(int id); IEnumerable GetProcessByName(string name); - void Start(string path); + Process Start(string path); Process Start(ProcessStartInfo startInfo); void WaitForExit(Process process); - void Kill(int processId); void SetPriority(int processId, ProcessPriorityClass priority); void KillAll(string processName); } @@ -27,12 +25,12 @@ public class ProcessProvider : IProcessProvider public const string NzbDroneProcessName = "NzbDrone"; public const string NzbDroneConsoleProcessName = "NzbDrone.Console"; - public ProcessInfo GetCurrentProcess() + public ProcessInfo GetCurrentProcess() { return ConvertToProcessInfo(Process.GetCurrentProcess()); } - public ProcessInfo GetProcessById(int id) + public ProcessInfo GetProcessById(int id) { Logger.Trace("Finding process with Id:{0}", id); @@ -50,17 +48,17 @@ public ProcessInfo GetProcessById(int id) return processInfo; } - public IEnumerable GetProcessByName(string name) + public IEnumerable GetProcessByName(string name) { return Process.GetProcessesByName(name).Select(ConvertToProcessInfo).Where(p => p != null); } - public void Start(string path) + public Process Start(string path) { - Process.Start(path); + return Start(new ProcessStartInfo(path)); } - public Process Start(ProcessStartInfo startInfo) + public Process Start(ProcessStartInfo startInfo) { Logger.Info("Starting process. [{0}]", startInfo.FileName); @@ -69,38 +67,19 @@ public Process Start(ProcessStartInfo startInfo) StartInfo = startInfo }; process.Start(); + return process; } - public void WaitForExit(Process process) + public void WaitForExit(Process process) { Logger.Trace("Waiting for process {0} to exit.", process.ProcessName); process.WaitForExit(); } - public void Kill(int processId) - { - if (processId == 0 || Process.GetProcesses().All(p => p.Id != processId)) - { - Logger.Warn("Cannot find process with id: {0}", processId); - return; - } - var process = Process.GetProcessById(processId); - if (process.HasExited) - { - return; - } - - Logger.Info("[{0}]: Killing process", process.Id); - process.Kill(); - Logger.Info("[{0}]: Waiting for exit", process.Id); - process.WaitForExit(); - Logger.Info("[{0}]: Process terminated successfully", process.Id); - } - - public void SetPriority(int processId, ProcessPriorityClass priority) + public void SetPriority(int processId, ProcessPriorityClass priority) { var process = Process.GetProcessById(processId); @@ -125,7 +104,7 @@ private static ProcessInfo ConvertToProcessInfo(Process process) }; } - public void KillAll(string processName) + public void KillAll(string processName) { var processToKill = GetProcessByName(processName); @@ -134,5 +113,27 @@ public void KillAll(string processName) Kill(processInfo.Id); } } + + private void Kill(int processId) + { + if (processId == 0 || Process.GetProcesses().All(p => p.Id != processId)) + { + Logger.Warn("Cannot find process with id: {0}", processId); + return; + } + + var process = Process.GetProcessById(processId); + + if (process.HasExited) + { + return; + } + + Logger.Info("[{0}]: Killing process", process.Id); + process.Kill(); + Logger.Info("[{0}]: Waiting for exit", process.Id); + process.WaitForExit(); + Logger.Info("[{0}]: Process terminated successfully", process.Id); + } } } \ No newline at end of file diff --git a/NzbDrone.Common/IServiceProvider.cs b/NzbDrone.Common/ServiceProvider.cs similarity index 94% rename from NzbDrone.Common/IServiceProvider.cs rename to NzbDrone.Common/ServiceProvider.cs index 37e97e8f3..71460b41a 100644 --- a/NzbDrone.Common/IServiceProvider.cs +++ b/NzbDrone.Common/ServiceProvider.cs @@ -41,7 +41,11 @@ public virtual bool IsServiceRunning(string name) var service = ServiceController.GetServices() .SingleOrDefault(s => String.Equals(s.ServiceName, name, StringComparison.InvariantCultureIgnoreCase)); - return service != null && (service.Status == ServiceControllerStatus.Running || service.Status == ServiceControllerStatus.StartPending); + return service != null && ( + service.Status != ServiceControllerStatus.Stopped || + service.Status == ServiceControllerStatus.StopPending || + service.Status == ServiceControllerStatus.Paused || + service.Status == ServiceControllerStatus.PausePending); } public virtual void Install(string serviceName) diff --git a/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs b/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs index 443f6cef8..402e11af1 100644 --- a/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs +++ b/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs @@ -33,12 +33,13 @@ public void Terminate() { try { + _logger.Info("NzbDrone Service is installed and running"); _serviceProvider.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME); } - catch (InvalidOperationException e) + catch (Exception e) { - _logger.WarnException("couldn't stop service", e); + _logger.ErrorException("couldn't stop service", e); } }