mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-16 11:37:58 +02:00
Added single instance policy
This commit is contained in:
parent
266d1a43d9
commit
c219be8c8d
@ -60,6 +60,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="ContainerFixture.cs" />
|
<Compile Include="ContainerFixture.cs" />
|
||||||
|
<Compile Include="NzbDroneProcessServiceFixture.cs" />
|
||||||
<Compile Include="RouterTest.cs" />
|
<Compile Include="RouterTest.cs" />
|
||||||
<Compile Include="MonitoringProviderTest.cs" />
|
<Compile Include="MonitoringProviderTest.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
91
src/NzbDrone.App.Test/NzbDroneProcessServiceFixture.cs
Normal file
91
src/NzbDrone.App.Test/NzbDroneProcessServiceFixture.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Common.Model;
|
||||||
|
using NzbDrone.Common.Processes;
|
||||||
|
using NzbDrone.Host;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
|
namespace NzbDrone.App.Test
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class NzbDroneProcessServiceFixture : TestBase<SingleInstancePolicy>
|
||||||
|
{
|
||||||
|
private const int CURRENT_PROCESS_ID = 5;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IProcessProvider>().Setup(c => c.GetCurrentProcess())
|
||||||
|
.Returns(new ProcessInfo() { Id = CURRENT_PROCESS_ID });
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_continue_if_only_instance()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IProcessProvider>()
|
||||||
|
.Setup(c => c.FindProcessByName(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME))
|
||||||
|
.Returns(new List<ProcessInfo>());
|
||||||
|
|
||||||
|
Mocker.GetMock<IProcessProvider>().Setup(c => c.FindProcessByName(ProcessProvider.NZB_DRONE_PROCESS_NAME))
|
||||||
|
.Returns(new List<ProcessInfo>
|
||||||
|
{
|
||||||
|
new ProcessInfo{Id = CURRENT_PROCESS_ID}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Subject.EnforceSingleInstance();
|
||||||
|
|
||||||
|
|
||||||
|
Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Never());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_enforce_if_another_console_is_running()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IProcessProvider>()
|
||||||
|
.Setup(c => c.FindProcessByName(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME))
|
||||||
|
.Returns(new List<ProcessInfo>
|
||||||
|
{
|
||||||
|
new ProcessInfo{Id = 10}
|
||||||
|
});
|
||||||
|
|
||||||
|
Mocker.GetMock<IProcessProvider>().Setup(c => c.FindProcessByName(ProcessProvider.NZB_DRONE_PROCESS_NAME))
|
||||||
|
.Returns(new List<ProcessInfo>
|
||||||
|
{
|
||||||
|
new ProcessInfo{Id = CURRENT_PROCESS_ID}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Assert.Throws<TerminateApplicationException>(() => Subject.EnforceSingleInstance());
|
||||||
|
Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Once());
|
||||||
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_another_gui_is_running()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IProcessProvider>()
|
||||||
|
.Setup(c => c.FindProcessByName(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME))
|
||||||
|
.Returns(new List<ProcessInfo>
|
||||||
|
{
|
||||||
|
new ProcessInfo{Id = CURRENT_PROCESS_ID}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Mocker.GetMock<IProcessProvider>().Setup(c => c.FindProcessByName(ProcessProvider.NZB_DRONE_PROCESS_NAME))
|
||||||
|
.Returns(new List<ProcessInfo>
|
||||||
|
{
|
||||||
|
new ProcessInfo{Id = 10}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Assert.Throws<TerminateApplicationException>(() => Subject.EnforceSingleInstance());
|
||||||
|
Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Once());
|
||||||
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ public interface IProcessProvider
|
|||||||
{
|
{
|
||||||
ProcessInfo GetCurrentProcess();
|
ProcessInfo GetCurrentProcess();
|
||||||
ProcessInfo GetProcessById(int id);
|
ProcessInfo GetProcessById(int id);
|
||||||
|
List<ProcessInfo> FindProcessByName(string name);
|
||||||
void OpenDefaultBrowser(string url);
|
void OpenDefaultBrowser(string url);
|
||||||
void WaitForExit(Process process);
|
void WaitForExit(Process process);
|
||||||
void SetPriority(int processId, ProcessPriorityClass priority);
|
void SetPriority(int processId, ProcessPriorityClass priority);
|
||||||
@ -74,6 +75,11 @@ public ProcessInfo GetProcessById(int id)
|
|||||||
return processInfo;
|
return processInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ProcessInfo> FindProcessByName(string name)
|
||||||
|
{
|
||||||
|
return Process.GetProcessesByName(name).Select(ConvertToProcessInfo).Where(c => c != null).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public void OpenDefaultBrowser(string url)
|
public void OpenDefaultBrowser(string url)
|
||||||
{
|
{
|
||||||
Logger.Info("Opening URL [{0}]", url);
|
Logger.Info("Opening URL [{0}]", url);
|
||||||
@ -213,23 +219,29 @@ private static ProcessInfo ConvertToProcessInfo(Process process)
|
|||||||
|
|
||||||
process.Refresh();
|
process.Refresh();
|
||||||
|
|
||||||
|
ProcessInfo processInfo = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (process.Id <= 0 || process.HasExited) return null;
|
if (process.Id <= 0) return null;
|
||||||
|
|
||||||
return new ProcessInfo
|
processInfo = new ProcessInfo();
|
||||||
|
processInfo.Id = process.Id;
|
||||||
|
processInfo.Name = process.ProcessName;
|
||||||
|
processInfo.StartPath = GetExeFileName(process);
|
||||||
|
|
||||||
|
if (process.HasExited)
|
||||||
{
|
{
|
||||||
Id = process.Id,
|
processInfo = null;
|
||||||
StartPath = GetExeFileName(process),
|
|
||||||
Name = process.ProcessName
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
catch (Win32Exception)
|
}
|
||||||
|
catch (Win32Exception e)
|
||||||
{
|
{
|
||||||
Logger.Warn("Coudn't get process info for " + process.ProcessName);
|
Logger.WarnException("Couldn't get process info for " + process.ProcessName, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return processInfo;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetExeFileName(Process process)
|
private static string GetExeFileName(Process process)
|
||||||
|
@ -32,8 +32,10 @@ public static void Main(string[] args)
|
|||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (TerminateApplicationException)
|
catch (TerminateApplicationException e)
|
||||||
{
|
{
|
||||||
|
Logger.Info("Application has been terminated. Reason " + e.Reason);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
using System;
|
using System.ServiceProcess;
|
||||||
using System.ServiceProcess;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Processes;
|
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Host.Owin;
|
using NzbDrone.Host.Owin;
|
||||||
|
|
||||||
@ -20,20 +18,20 @@ public class NzbDroneServiceFactory : ServiceBase, INzbDroneServiceFactory
|
|||||||
private readonly IConfigFileProvider _configFileProvider;
|
private readonly IConfigFileProvider _configFileProvider;
|
||||||
private readonly IRuntimeInfo _runtimeInfo;
|
private readonly IRuntimeInfo _runtimeInfo;
|
||||||
private readonly IHostController _hostController;
|
private readonly IHostController _hostController;
|
||||||
private readonly IProcessProvider _processProvider;
|
|
||||||
private readonly PriorityMonitor _priorityMonitor;
|
private readonly PriorityMonitor _priorityMonitor;
|
||||||
private readonly IStartupArguments _startupArguments;
|
private readonly IStartupArguments _startupArguments;
|
||||||
|
private readonly IBrowserService _browserService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public NzbDroneServiceFactory(IConfigFileProvider configFileProvider, IHostController hostController, IRuntimeInfo runtimeInfo,
|
public NzbDroneServiceFactory(IConfigFileProvider configFileProvider, IHostController hostController,
|
||||||
IProcessProvider processProvider, PriorityMonitor priorityMonitor, IStartupArguments startupArguments, Logger logger)
|
IRuntimeInfo runtimeInfo, PriorityMonitor priorityMonitor, IStartupArguments startupArguments, IBrowserService browserService, Logger logger)
|
||||||
{
|
{
|
||||||
_configFileProvider = configFileProvider;
|
_configFileProvider = configFileProvider;
|
||||||
_hostController = hostController;
|
_hostController = hostController;
|
||||||
_runtimeInfo = runtimeInfo;
|
_runtimeInfo = runtimeInfo;
|
||||||
_processProvider = processProvider;
|
|
||||||
_priorityMonitor = priorityMonitor;
|
_priorityMonitor = priorityMonitor;
|
||||||
_startupArguments = startupArguments;
|
_startupArguments = startupArguments;
|
||||||
|
_browserService = browserService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,15 +48,7 @@ public void Start()
|
|||||||
_runtimeInfo.IsUserInteractive &&
|
_runtimeInfo.IsUserInteractive &&
|
||||||
_configFileProvider.LaunchBrowser)
|
_configFileProvider.LaunchBrowser)
|
||||||
{
|
{
|
||||||
try
|
_browserService.LaunchWebUI();
|
||||||
{
|
|
||||||
_logger.Info("Starting default browser. {0}", _hostController.AppUrl);
|
|
||||||
_processProvider.OpenDefaultBrowser(_hostController.AppUrl);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Failed to open URL in default browser.", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_priorityMonitor.Start();
|
_priorityMonitor.Start();
|
||||||
|
@ -7,9 +7,11 @@
|
|||||||
|
|
||||||
namespace NzbDrone.Host
|
namespace NzbDrone.Host
|
||||||
{
|
{
|
||||||
public static class Bootstrap
|
public class Bootstrap
|
||||||
{
|
{
|
||||||
public static IContainer Start(StartupArguments args, IUserAlert userAlert)
|
public IContainer Container { get; private set; }
|
||||||
|
|
||||||
|
public Bootstrap(StartupArguments args, IUserAlert userAlert)
|
||||||
{
|
{
|
||||||
var logger = NzbDroneLogger.GetLogger();
|
var logger = NzbDroneLogger.GetLogger();
|
||||||
|
|
||||||
@ -21,15 +23,25 @@ public static IContainer Start(StartupArguments args, IUserAlert userAlert)
|
|||||||
|
|
||||||
if (!PlatformValidation.IsValidate(userAlert))
|
if (!PlatformValidation.IsValidate(userAlert))
|
||||||
{
|
{
|
||||||
throw new TerminateApplicationException();
|
throw new TerminateApplicationException("Missing system requirements");
|
||||||
}
|
}
|
||||||
|
|
||||||
var container = MainAppContainerBuilder.BuildContainer(args);
|
Container = MainAppContainerBuilder.BuildContainer(args);
|
||||||
|
|
||||||
DbFactory.RegisterDatabase(container);
|
|
||||||
container.Resolve<Router>().Route();
|
|
||||||
|
|
||||||
return container;
|
}
|
||||||
}
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
DbFactory.RegisterDatabase(Container);
|
||||||
|
Container.Resolve<Router>().Route();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void EnsureSingleInstance()
|
||||||
|
{
|
||||||
|
Container.Resolve<ISingleInstancePolicy>().EnforceSingleInstance();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
40
src/NzbDrone.Host/BrowserService.cs
Normal file
40
src/NzbDrone.Host/BrowserService.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Processes;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
|
namespace NzbDrone.Host
|
||||||
|
{
|
||||||
|
public interface IBrowserService
|
||||||
|
{
|
||||||
|
void LaunchWebUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BrowserService : IBrowserService
|
||||||
|
{
|
||||||
|
private readonly IProcessProvider _processProvider;
|
||||||
|
private readonly IConfigFileProvider _configFileProvider;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public BrowserService(IProcessProvider processProvider, IConfigFileProvider configFileProvider, Logger logger)
|
||||||
|
{
|
||||||
|
_processProvider = processProvider;
|
||||||
|
_configFileProvider = configFileProvider;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LaunchWebUI()
|
||||||
|
{
|
||||||
|
var url = string.Format("http://localhost:{0}", _configFileProvider.Port);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.Info("Starting default browser. {0}", url);
|
||||||
|
_processProvider.OpenDefaultBrowser(url);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Couldn't open defult browser to " + url, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -116,6 +116,8 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="AccessControl\FirewallAdapter.cs" />
|
<Compile Include="AccessControl\FirewallAdapter.cs" />
|
||||||
<Compile Include="AccessControl\UrlAclAdapter.cs" />
|
<Compile Include="AccessControl\UrlAclAdapter.cs" />
|
||||||
|
<Compile Include="BrowserService.cs" />
|
||||||
|
<Compile Include="NzbDroneProcessService.cs" />
|
||||||
<Compile Include="IUserAlert.cs" />
|
<Compile Include="IUserAlert.cs" />
|
||||||
<Compile Include="Owin\NlogTextWriter.cs" />
|
<Compile Include="Owin\NlogTextWriter.cs" />
|
||||||
<Compile Include="Owin\OwinServiceProvider.cs" />
|
<Compile Include="Owin\OwinServiceProvider.cs" />
|
||||||
|
47
src/NzbDrone.Host/NzbDroneProcessService.cs
Normal file
47
src/NzbDrone.Host/NzbDroneProcessService.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Processes;
|
||||||
|
|
||||||
|
namespace NzbDrone.Host
|
||||||
|
{
|
||||||
|
public interface ISingleInstancePolicy
|
||||||
|
{
|
||||||
|
void EnforceSingleInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SingleInstancePolicy : ISingleInstancePolicy
|
||||||
|
{
|
||||||
|
private readonly IProcessProvider _processProvider;
|
||||||
|
private readonly IBrowserService _browserService;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public SingleInstancePolicy(IProcessProvider processProvider, IBrowserService browserService, Logger logger)
|
||||||
|
{
|
||||||
|
_processProvider = processProvider;
|
||||||
|
_browserService = browserService;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnforceSingleInstance()
|
||||||
|
{
|
||||||
|
if (IsAlreadyRunning())
|
||||||
|
{
|
||||||
|
_logger.Warn("Another instance of NzbDrone is already running.");
|
||||||
|
_browserService.LaunchWebUI();
|
||||||
|
throw new TerminateApplicationException("Another instance is already running");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsAlreadyRunning()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@
|
|||||||
{
|
{
|
||||||
public interface IHostController
|
public interface IHostController
|
||||||
{
|
{
|
||||||
string AppUrl { get; }
|
|
||||||
void StartServer();
|
void StartServer();
|
||||||
void StopServer();
|
void StopServer();
|
||||||
}
|
}
|
||||||
|
@ -107,11 +107,6 @@ private void BuildApp(IAppBuilder appBuilder)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string AppUrl
|
|
||||||
{
|
|
||||||
get { return string.Format("http://localhost:{0}", _configFileProvider.Port); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StopServer()
|
public void StopServer()
|
||||||
{
|
{
|
||||||
if (_host == null) return;
|
if (_host == null) return;
|
||||||
|
@ -4,5 +4,11 @@ namespace NzbDrone.Host
|
|||||||
{
|
{
|
||||||
public class TerminateApplicationException : ApplicationException
|
public class TerminateApplicationException : ApplicationException
|
||||||
{
|
{
|
||||||
|
public TerminateApplicationException(string reason)
|
||||||
|
{
|
||||||
|
Reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Reason { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Processes;
|
using NzbDrone.Host;
|
||||||
using NzbDrone.Host.Owin;
|
using NzbDrone.Host.Owin;
|
||||||
|
|
||||||
namespace NzbDrone.SysTray
|
namespace NzbDrone.SysTray
|
||||||
@ -14,16 +14,14 @@ public interface ISystemTrayApp
|
|||||||
|
|
||||||
public class SystemTrayApp : Form, ISystemTrayApp
|
public class SystemTrayApp : Form, ISystemTrayApp
|
||||||
{
|
{
|
||||||
private readonly IProcessProvider _processProvider;
|
private readonly IBrowserService _browserService;
|
||||||
private readonly IHostController _hostController;
|
|
||||||
|
|
||||||
private readonly NotifyIcon _trayIcon = new NotifyIcon();
|
private readonly NotifyIcon _trayIcon = new NotifyIcon();
|
||||||
private readonly ContextMenu _trayMenu = new ContextMenu();
|
private readonly ContextMenu _trayMenu = new ContextMenu();
|
||||||
|
|
||||||
public SystemTrayApp(IProcessProvider processProvider, IHostController hostController)
|
public SystemTrayApp(IBrowserService browserService)
|
||||||
{
|
{
|
||||||
_processProvider = processProvider;
|
_browserService = browserService;
|
||||||
_hostController = hostController;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -84,7 +82,7 @@ private void LaunchBrowser(object sender, EventArgs e)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_processProvider.OpenDefaultBrowser(_hostController.AppUrl);
|
_browserService.LaunchWebUI();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
@ -20,12 +20,18 @@ public static void Main(string[] args)
|
|||||||
|
|
||||||
LogTargets.Register(startupArgs, false, true);
|
LogTargets.Register(startupArgs, false, true);
|
||||||
|
|
||||||
var container = Bootstrap.Start(startupArgs, new MessageBoxUserAlert());
|
var bootstrap = new Bootstrap(startupArgs, new MessageBoxUserAlert());
|
||||||
container.Register<ISystemTrayApp, SystemTrayApp>();
|
|
||||||
container.Resolve<ISystemTrayApp>().Start();
|
bootstrap.EnsureSingleInstance();
|
||||||
|
|
||||||
|
bootstrap.Start();
|
||||||
|
bootstrap.Container.Register<ISystemTrayApp, SystemTrayApp>();
|
||||||
|
bootstrap.Container.Resolve<ISystemTrayApp>().Start();
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (TerminateApplicationException)
|
catch (TerminateApplicationException e)
|
||||||
{
|
{
|
||||||
|
Logger.Info("Application has been terminated. Reason " + e.Reason);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -34,5 +40,7 @@ public static void Main(string[] args)
|
|||||||
MessageBox.Show(text: message, buttons: MessageBoxButtons.OK, icon: MessageBoxIcon.Error, caption: "Epic Fail!");
|
MessageBox.Show(text: message, buttons: MessageBoxButtons.OK, icon: MessageBoxIcon.Error, caption: "Epic Fail!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user