Shutdown! Restart working for services
This commit is contained in:
parent
119a4ff39c
commit
f69bb79077
|
@ -13,25 +13,23 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||||
bool IsUserInteractive { get; }
|
bool IsUserInteractive { get; }
|
||||||
bool IsAdmin { get; }
|
bool IsAdmin { get; }
|
||||||
bool IsWindowsService { get; }
|
bool IsWindowsService { get; }
|
||||||
|
bool IsConsole { get; }
|
||||||
|
bool IsRunning { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RuntimeInfo : IRuntimeInfo
|
public class RuntimeInfo : IRuntimeInfo
|
||||||
{
|
{
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
private static readonly string ProcessName = Process.GetCurrentProcess().ProcessName.ToLower();
|
||||||
|
|
||||||
public RuntimeInfo(Logger logger, IServiceProvider serviceProvider)
|
public RuntimeInfo(Logger logger, IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
IsWindowsService = !IsUserInteractive &&
|
IsWindowsService = !IsUserInteractive &&
|
||||||
OsInfo.IsWindows &&
|
OsInfo.IsWindows &&
|
||||||
serviceProvider.ServiceExist(ServiceProvider.NZBDRONE_SERVICE_NAME) &&
|
serviceProvider.ServiceExist(ServiceProvider.NZBDRONE_SERVICE_NAME) &&
|
||||||
serviceProvider.GetStatus(ServiceProvider.NZBDRONE_SERVICE_NAME) == ServiceControllerStatus.StartPending;
|
serviceProvider.GetStatus(ServiceProvider.NZBDRONE_SERVICE_NAME) == ServiceControllerStatus.StartPending;
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsUserInteractive
|
|
||||||
{
|
|
||||||
get { return Environment.UserInteractive; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RuntimeInfo()
|
static RuntimeInfo()
|
||||||
|
@ -39,6 +37,11 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||||
IsProduction = InternalIsProduction();
|
IsProduction = InternalIsProduction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsUserInteractive
|
||||||
|
{
|
||||||
|
get { return Environment.UserInteractive; }
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsAdmin
|
public bool IsAdmin
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -58,7 +61,18 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||||
|
|
||||||
public bool IsWindowsService { get; private set; }
|
public bool IsWindowsService { get; private set; }
|
||||||
|
|
||||||
private static readonly string ProcessName = Process.GetCurrentProcess().ProcessName.ToLower();
|
public bool IsConsole
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (OsInfo.IsWindows &&
|
||||||
|
IsUserInteractive &&
|
||||||
|
ProcessName.Equals("NzbDrone.Console.exe", StringComparison.InvariantCultureIgnoreCase)) ||
|
||||||
|
OsInfo.IsLinux;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRunning { get; set; }
|
||||||
|
|
||||||
public static bool IsProduction { get; private set; }
|
public static bool IsProduction { get; private set; }
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ using NLog;
|
||||||
using NLog.Config;
|
using NLog.Config;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
using NzbDrone.Common.Processes;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Instrumentation
|
namespace NzbDrone.Common.Instrumentation
|
||||||
{
|
{
|
||||||
|
@ -30,7 +31,7 @@ namespace NzbDrone.Common.Instrumentation
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (inConsole && (OsInfo.IsLinux || new RuntimeInfo(null, new ServiceProvider()).IsUserInteractive))
|
if (inConsole && (OsInfo.IsLinux || new RuntimeInfo(null, new ServiceProvider(new ProcessProvider())).IsUserInteractive))
|
||||||
{
|
{
|
||||||
RegisterConsole();
|
RegisterConsole();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Instrumentation;
|
using NzbDrone.Common.Instrumentation;
|
||||||
|
using NzbDrone.Common.Processes;
|
||||||
|
|
||||||
namespace NzbDrone.Common
|
namespace NzbDrone.Common
|
||||||
{
|
{
|
||||||
|
@ -20,14 +21,22 @@ namespace NzbDrone.Common
|
||||||
void Stop(string serviceName);
|
void Stop(string serviceName);
|
||||||
void Start(string serviceName);
|
void Start(string serviceName);
|
||||||
ServiceControllerStatus GetStatus(string serviceName);
|
ServiceControllerStatus GetStatus(string serviceName);
|
||||||
|
void Restart(string serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ServiceProvider : IServiceProvider
|
public class ServiceProvider : IServiceProvider
|
||||||
{
|
{
|
||||||
public const string NZBDRONE_SERVICE_NAME = "NzbDrone";
|
public const string NZBDRONE_SERVICE_NAME = "NzbDrone";
|
||||||
|
|
||||||
|
private readonly IProcessProvider _processProvider;
|
||||||
|
|
||||||
private static readonly Logger Logger = NzbDroneLogger.GetLogger();
|
private static readonly Logger Logger = NzbDroneLogger.GetLogger();
|
||||||
|
|
||||||
|
public ServiceProvider(IProcessProvider processProvider)
|
||||||
|
{
|
||||||
|
_processProvider = processProvider;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual bool ServiceExist(string name)
|
public virtual bool ServiceExist(string name)
|
||||||
{
|
{
|
||||||
Logger.Debug("Checking if service {0} exists.", name);
|
Logger.Debug("Checking if service {0} exists.", name);
|
||||||
|
@ -173,5 +182,12 @@ namespace NzbDrone.Common
|
||||||
Logger.Error("Service start request has timed out. {0}", service.Status);
|
Logger.Error("Service start request has timed out. {0}", service.Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Restart(string serviceName)
|
||||||
|
{
|
||||||
|
var args = String.Format("/C net.exe stop \"{0}\" && net.exe start \"{0}\"", serviceName);
|
||||||
|
|
||||||
|
_processProvider.Start("cmd.exe", args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Lifecycle
|
||||||
|
{
|
||||||
|
public class ApplicationRestartRequested : IEvent
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Lifecycle.Commands
|
||||||
|
{
|
||||||
|
public class RestartCommand : Command
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Lifecycle.Commands
|
||||||
|
{
|
||||||
|
public class ShutdownCommand : Command
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
using NzbDrone.Common.Processes;
|
||||||
|
using NzbDrone.Core.Lifecycle.Commands;
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using IServiceProvider = NzbDrone.Common.IServiceProvider;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Lifecycle
|
||||||
|
{
|
||||||
|
public class LifestyleService: IExecute<ShutdownCommand>, IExecute<RestartCommand>
|
||||||
|
{
|
||||||
|
private readonly IEventAggregator _eventAggregator;
|
||||||
|
private readonly IRuntimeInfo _runtimeInfo;
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private readonly IProcessProvider _processProvider;
|
||||||
|
|
||||||
|
|
||||||
|
public LifestyleService(IEventAggregator eventAggregator,
|
||||||
|
IRuntimeInfo runtimeInfo,
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
|
IProcessProvider processProvider)
|
||||||
|
{
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
|
_runtimeInfo = runtimeInfo;
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
_processProvider = processProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(ShutdownCommand message)
|
||||||
|
{
|
||||||
|
if (_runtimeInfo.IsWindowsService)
|
||||||
|
{
|
||||||
|
_serviceProvider.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_eventAggregator.PublishEvent(new ApplicationShutdownRequested());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(RestartCommand message)
|
||||||
|
{
|
||||||
|
if (_runtimeInfo.IsWindowsService)
|
||||||
|
{
|
||||||
|
_serviceProvider.Restart(ServiceProvider.NZBDRONE_SERVICE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
_eventAggregator.PublishEvent(new ApplicationRestartRequested());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -290,6 +290,10 @@
|
||||||
<Compile Include="Instrumentation\Commands\TrimLogCommand.cs" />
|
<Compile Include="Instrumentation\Commands\TrimLogCommand.cs" />
|
||||||
<Compile Include="Instrumentation\DeleteLogFilesService.cs" />
|
<Compile Include="Instrumentation\DeleteLogFilesService.cs" />
|
||||||
<Compile Include="MediaFiles\Commands\RescanSeriesCommand.cs" />
|
<Compile Include="MediaFiles\Commands\RescanSeriesCommand.cs" />
|
||||||
|
<Compile Include="Lifecycle\Commands\ShutdownCommand.cs" />
|
||||||
|
<Compile Include="Lifecycle\Commands\RestartCommand.cs" />
|
||||||
|
<Compile Include="Lifecycle\ApplicationRestartRequested.cs" />
|
||||||
|
<Compile Include="Lifecycle\LifestyleService.cs" />
|
||||||
<Compile Include="MediaFiles\Commands\RenameFilesCommand.cs" />
|
<Compile Include="MediaFiles\Commands\RenameFilesCommand.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeFileMoveResult.cs" />
|
<Compile Include="MediaFiles\EpisodeFileMoveResult.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecification.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecification.cs" />
|
||||||
|
|
|
@ -2,18 +2,19 @@
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Lifecycle;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Host.Owin;
|
using NzbDrone.Host.Owin;
|
||||||
|
|
||||||
namespace NzbDrone.Host
|
namespace NzbDrone.Host
|
||||||
{
|
{
|
||||||
public interface INzbDroneServiceFactory
|
public interface INzbDroneServiceFactory
|
||||||
{
|
{
|
||||||
bool IsServiceStopped { get; }
|
|
||||||
ServiceBase Build();
|
ServiceBase Build();
|
||||||
void Start();
|
void Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NzbDroneServiceFactory : ServiceBase, INzbDroneServiceFactory
|
public class NzbDroneServiceFactory : ServiceBase, INzbDroneServiceFactory, IHandle<ApplicationShutdownRequested>
|
||||||
{
|
{
|
||||||
private readonly IConfigFileProvider _configFileProvider;
|
private readonly IConfigFileProvider _configFileProvider;
|
||||||
private readonly IRuntimeInfo _runtimeInfo;
|
private readonly IRuntimeInfo _runtimeInfo;
|
||||||
|
@ -42,6 +43,7 @@ namespace NzbDrone.Host
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
|
_runtimeInfo.IsRunning = true;
|
||||||
_hostController.StartServer();
|
_hostController.StartServer();
|
||||||
|
|
||||||
if (!_startupContext.Flags.Contains(StartupContext.NO_BROWSER)
|
if (!_startupContext.Flags.Contains(StartupContext.NO_BROWSER)
|
||||||
|
@ -55,18 +57,28 @@ namespace NzbDrone.Host
|
||||||
|
|
||||||
protected override void OnStop()
|
protected override void OnStop()
|
||||||
{
|
{
|
||||||
_logger.Info("Attempting to stop application.");
|
Shutdown();
|
||||||
_hostController.StopServer();
|
|
||||||
_logger.Info("Application has finished stop routine.");
|
|
||||||
IsServiceStopped = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsServiceStopped { get; private set; }
|
|
||||||
|
|
||||||
public ServiceBase Build()
|
public ServiceBase Build()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
private void Shutdown()
|
||||||
|
{
|
||||||
|
_logger.Info("Attempting to stop application.");
|
||||||
|
_hostController.StopServer();
|
||||||
|
_logger.Info("Application has finished stop routine.");
|
||||||
|
_runtimeInfo.IsRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(ApplicationShutdownRequested message)
|
||||||
|
{
|
||||||
|
if (!_runtimeInfo.IsWindowsService)
|
||||||
|
{
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -72,9 +72,9 @@ namespace NzbDrone.Host
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var serviceFactory = _container.Resolve<INzbDroneServiceFactory>();
|
var runTimeInfo = _container.Resolve<IRuntimeInfo>();
|
||||||
|
|
||||||
while (!serviceFactory.IsServiceStopped)
|
while (runTimeInfo.IsRunning)
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,15 @@ namespace NzbDrone.SysTray
|
||||||
_trayIcon.Dispose();
|
_trayIcon.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Dispose(isDisposing);
|
if (InvokeRequired)
|
||||||
|
{
|
||||||
|
base.Invoke(new MethodInvoker(() => Dispose(isDisposing)));
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnExit(object sender, EventArgs e)
|
private void OnExit(object sender, EventArgs e)
|
||||||
|
|
Loading…
Reference in New Issue