Service kills other instances on start.

This commit is contained in:
kayone 2013-11-25 23:08:12 -08:00
parent 1e6817220a
commit d42a63a480
6 changed files with 54 additions and 25 deletions

View File

@ -34,7 +34,7 @@ namespace NzbDrone.App.Test
});
Subject.EnforceSingleInstance();
Subject.PreventStartIfAlreadyRunning();
Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Never());
@ -59,7 +59,7 @@ namespace NzbDrone.App.Test
Assert.Throws<TerminateApplicationException>(() => Subject.EnforceSingleInstance());
Assert.Throws<TerminateApplicationException>(() => Subject.PreventStartIfAlreadyRunning());
Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Once());
ExceptionVerification.ExpectedWarns(1);
}
@ -83,7 +83,7 @@ namespace NzbDrone.App.Test
Assert.Throws<TerminateApplicationException>(() => Subject.EnforceSingleInstance());
Assert.Throws<TerminateApplicationException>(() => Subject.PreventStartIfAlreadyRunning());
Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Once());
ExceptionVerification.ExpectedWarns(1);
}

View File

@ -24,9 +24,9 @@ namespace NzbDrone.Common
Console.WriteLine();
Console.WriteLine(" Usage: {0} <command> ", Process.GetCurrentProcess().MainModule.ModuleName);
Console.WriteLine(" Commands:");
Console.WriteLine(" /{0} Install the application as a Windows Service ({1}).", StartupArguments.INSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
Console.WriteLine(" /{0} Uninstall already installed Windows Service ({1}).", StartupArguments.UNINSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
Console.WriteLine(" /{0} Don't open NzbDrone in a browser", StartupArguments.NO_BROWSER);
Console.WriteLine(" /{0} Install the application as a Windows Service ({1}).", StartupContext.INSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
Console.WriteLine(" /{0} Uninstall already installed Windows Service ({1}).", StartupContext.UNINSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
Console.WriteLine(" /{0} Don't open NzbDrone in a browser", StartupContext.NO_BROWSER);
Console.WriteLine(" <No Arguments> Run application in console mode.");
}

View File

@ -20,6 +20,7 @@ namespace NzbDrone.Common.Processes
void WaitForExit(Process process);
void SetPriority(int processId, ProcessPriorityClass priority);
void KillAll(string processName);
void Kill(int processId);
bool Exists(string processName);
ProcessPriorityClass GetCurrentProcessPriority();
Process Start(string path, string args = null, Action<string> onOutputDataReceived = null, Action<string> onErrorDataReceived = null);
@ -254,7 +255,7 @@ namespace NzbDrone.Common.Processes
return process.Modules.Cast<ProcessModule>().FirstOrDefault(module => module.ModuleName.ToLower().EndsWith(".exe")).FileName;
}
private void Kill(int processId)
public void Kill(int processId)
{
var process = Process.GetProcesses().FirstOrDefault(p => p.Id == processId);

View File

@ -47,7 +47,7 @@ namespace NzbDrone.Host
}
catch (TerminateApplicationException e)
{
Logger.Info("Application has been terminated. Reason " + e.Reason);
Logger.Info(e.Message);
}
}
@ -56,7 +56,7 @@ namespace NzbDrone.Host
{
if (!IsInUtilityMode(applicationModes))
{
EnsureSingleInstance();
EnsureSingleInstance(applicationModes == ApplicationModes.Service);
}
DbFactory.RegisterDatabase(_container);
@ -78,9 +78,18 @@ namespace NzbDrone.Host
}
}
private static void EnsureSingleInstance()
private static void EnsureSingleInstance(bool isService)
{
_container.Resolve<ISingleInstancePolicy>().EnforceSingleInstance();
var instancePolicy = _container.Resolve<ISingleInstancePolicy>();
if (isService)
{
instancePolicy.KillAllOtherInstance();
}
else
{
instancePolicy.PreventStartIfAlreadyRunning();
}
}

View File

@ -1,4 +1,6 @@
using System.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Processes;
@ -6,7 +8,8 @@ namespace NzbDrone.Host
{
public interface ISingleInstancePolicy
{
void EnforceSingleInstance();
void PreventStartIfAlreadyRunning();
void KillAllOtherInstance();
}
public class SingleInstancePolicy : ISingleInstancePolicy
@ -22,7 +25,7 @@ namespace NzbDrone.Host
_logger = logger;
}
public void EnforceSingleInstance()
public void PreventStartIfAlreadyRunning()
{
if (IsAlreadyRunning())
{
@ -32,16 +35,34 @@ namespace NzbDrone.Host
}
}
private bool IsAlreadyRunning()
public void KillAllOtherInstance()
{
var currentId = _processProvider.GetCurrentProcess().Id;
var consoleIds = _processProvider.FindProcessByName(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME).Select(c => c.Id);
var guiIds = _processProvider.FindProcessByName(ProcessProvider.NZB_DRONE_PROCESS_NAME).Select(c => c.Id);
var otherProcesses = consoleIds.Union(guiIds).Except(new[] { currentId });
return otherProcesses.Any();
foreach (var processId in GetOtherNzbDroneProcessIds())
{
_processProvider.Kill(processId);
}
}
private bool IsAlreadyRunning()
{
return GetOtherNzbDroneProcessIds().Any();
}
private List<int> GetOtherNzbDroneProcessIds()
{
var currentId = _processProvider.GetCurrentProcess().Id;
var consoleIds = _processProvider.FindProcessByName(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME)
.Select(c => c.Id);
var winformIds = _processProvider.FindProcessByName(ProcessProvider.NZB_DRONE_PROCESS_NAME).Select(c => c.Id);
var otherProcesses = consoleIds.Union(winformIds).Except(new[] { currentId }).ToList();
if (otherProcesses.Any())
{
_logger.Info("{0} instance(s) of NzbDrone are running", otherProcesses.Count);
}
return otherProcesses;
}
}
}

View File

@ -5,10 +5,8 @@ namespace NzbDrone.Host
public class TerminateApplicationException : ApplicationException
{
public TerminateApplicationException(string reason)
: base("Application is being terminated. Reason : " + reason)
{
Reason = reason;
}
public string Reason { get; private set; }
}
}