diff --git a/NzbDrone.6.0.ReSharper b/NzbDrone.6.0.ReSharper index fc6b1c5c3..c52dd4866 100644 --- a/NzbDrone.6.0.ReSharper +++ b/NzbDrone.6.0.ReSharper @@ -87,4 +87,9 @@ + + + 43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD/d:Content + + \ No newline at end of file diff --git a/NzbDrone/Application.cs b/NzbDrone/Application.cs new file mode 100644 index 000000000..eee088d86 --- /dev/null +++ b/NzbDrone/Application.cs @@ -0,0 +1,129 @@ +using System; +using System.Diagnostics; +using System.Net; +using System.Threading; +using System.Timers; +using NLog; +using NzbDrone.Providers; + +namespace NzbDrone +{ + internal class Application + { + private static readonly Logger Logger = LogManager.GetLogger("Application"); + + private readonly ConfigProvider _configProvider; + private readonly WebClient _webClient; + private readonly IISProvider _iisProvider; + private readonly ConsoleProvider _consoleProvider; + private readonly DebuggerProvider _debuggerProvider; + private readonly EnviromentProvider _enviromentProvider; + private readonly ProcessProvider _processProvider; + + public Application(ConfigProvider configProvider, WebClient webClient, IISProvider iisProvider, ConsoleProvider consoleProvider, + DebuggerProvider debuggerProvider, EnviromentProvider enviromentProvider, ProcessProvider processProvider) + { + _configProvider = configProvider; + _webClient = webClient; + _iisProvider = iisProvider; + _consoleProvider = consoleProvider; + _debuggerProvider = debuggerProvider; + _enviromentProvider = enviromentProvider; + _processProvider = processProvider; + + _configProvider.ConfigureNlog(); + _configProvider.CreateDefaultConfigFile(); + Logger.Info("Starting NZBDrone. Start-up Path:'{0}'", _configProvider.ApplicationRoot); + Thread.CurrentThread.Name = "Host"; + + AppDomain.CurrentDomain.UnhandledException += ((s, e) => AppDomainException(e)); + + AppDomain.CurrentDomain.ProcessExit += ProgramExited; + AppDomain.CurrentDomain.DomainUnload += ProgramExited; + } + + internal void Start() + { + _iisProvider.StopServer(); + _iisProvider.StartServer(); + + _debuggerProvider.Attach(); + + var prioCheckTimer = new System.Timers.Timer(5000); + prioCheckTimer.Elapsed += EnsurePriority; + prioCheckTimer.Enabled = true; + + if (_enviromentProvider.IsUserInteractive && _configProvider.LaunchBrowser) + { + try + { + Logger.Info("Starting default browser. {0}", _iisProvider.AppUrl); + _processProvider.Start(_iisProvider.AppUrl); + } + catch (Exception e) + { + Logger.ErrorException("Failed to open URL in default browser.", e); + } + + _consoleProvider.WaitForClose(); + return; + } + + try + { + _webClient.DownloadString(_iisProvider.AppUrl); + } + catch (Exception e) + { + Logger.ErrorException("Failed to load home page.", e); + } + } + + internal void Stop() + { + + } + + + private void AppDomainException(object excepion) + { + Console.WriteLine("EPIC FAIL: {0}", excepion); + Logger.Fatal("EPIC FAIL: {0}", excepion); + +#if RELEASE + new Client + { + ApiKey = "43BBF60A-EB2A-4C1C-B09E-422ADF637265", + ApplicationName = "NZBDrone", + CurrentException = excepion as Exception + }.Submit(); +#endif + } + + + internal void EnsurePriority(object sender, ElapsedEventArgs e) + { + var currentProcessId = _processProvider.GetCurrentProcessId(); + if (_processProvider.GetProcessPriority(currentProcessId) != ProcessPriorityClass.Normal) + { + _processProvider.SetPriority(_processProvider.GetCurrentProcessId(), ProcessPriorityClass.Normal); + } + + var iisProcessPriority = _processProvider.GetProcessPriority(_iisProvider.IISProcessId); + if (iisProcessPriority != ProcessPriorityClass.Normal && iisProcessPriority != ProcessPriorityClass.AboveNormal) + { + _processProvider.SetPriority(_iisProvider.IISProcessId, ProcessPriorityClass.Normal); + } + } + + private void ProgramExited(object sender, EventArgs e) + { + _iisProvider.StopServer(); + } + + } + + + +} + diff --git a/NzbDrone/NzbDrone.csproj b/NzbDrone/NzbDrone.csproj index 9f4666949..d18b326ca 100644 --- a/NzbDrone/NzbDrone.csproj +++ b/NzbDrone/NzbDrone.csproj @@ -67,6 +67,9 @@ False ..\Libraries\Exceptioneer.WindowsFormsClient.dll + + ..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll + False ..\Libraries\NLog.dll @@ -82,19 +85,25 @@ + + + Component - + + + + diff --git a/NzbDrone/Program.cs b/NzbDrone/Program.cs index 8bceb0149..619245c57 100644 --- a/NzbDrone/Program.cs +++ b/NzbDrone/Program.cs @@ -1,174 +1,30 @@ using System; -using System.Diagnostics; -using System.Net; -using System.Threading; -using System.Timers; -using Exceptioneer.WindowsFormsClient; using NLog; -using NzbDrone.Providers; +using Ninject; namespace NzbDrone { - internal static class Program + internal static class Program { - private static readonly Logger Logger = LogManager.GetLogger("Application"); + public static readonly StandardKernel Kernel = new StandardKernel(); - static readonly ConfigProvider ConfigProvider = new ConfigProvider(); - static readonly IISControllerProvider IISController = new IISControllerProvider(ConfigProvider); + private static readonly Logger Logger = LogManager.GetLogger("Main"); private static void Main() { try { - - - ConfigProvider.ConfigureNlog(); - ConfigProvider.CreateDefaultConfigFile(); - Logger.Info("Starting NZBDrone. Start-up Path:'{0}'", ConfigProvider.ApplicationRoot); - Thread.CurrentThread.Name = "Host"; - - Process currentProcess = Process.GetCurrentProcess(); - - var prioCheckTimer = new System.Timers.Timer(5000); - prioCheckTimer.Elapsed += prioCheckTimer_Elapsed; - prioCheckTimer.Enabled = true; - - currentProcess.EnableRaisingEvents = true; - currentProcess.Exited += ProgramExited; - - AppDomain.CurrentDomain.UnhandledException += ((s, e) => AppDomainException(e)); - AppDomain.CurrentDomain.ProcessExit += ProgramExited; - AppDomain.CurrentDomain.DomainUnload += ProgramExited; - - IISController.StopServer(); - IISController.StartServer(); - -#if DEBUG - Attach(); -#endif - - if (!Environment.UserInteractive || !ConfigProvider.LaunchBrowser) - { - try - { - new WebClient().DownloadString(IISController.AppUrl); - } - catch (Exception e) - { - Logger.ErrorException("Failed to load home page.", e); - } - } - else - { - try - { - Logger.Info("Starting default browser. {0}", IISController.AppUrl); - Process.Start(IISController.AppUrl); - } - catch (Exception e) - { - Logger.ErrorException("Failed to open URL in default browser.", e); - } - while (true) - { - Console.ReadLine(); - } - } + Console.WriteLine("Starting Console."); + Kernel.Get().Start(); } catch (Exception e) { - AppDomainException(e); + Console.WriteLine(e.ToString()); + Logger.Fatal(e.ToString()); } Console.WriteLine("Press enter to exit."); Console.ReadLine(); } - - private static void prioCheckTimer_Elapsed(object sender, ElapsedEventArgs e) - { - Process currentProcess = Process.GetCurrentProcess(); - if (currentProcess.PriorityClass != ProcessPriorityClass.Normal) - { - SetPriority(currentProcess); - } - - - if (IISControllerProvider.IISProcess != null) - { - IISControllerProvider.IISProcess.Refresh(); - - if (IISControllerProvider.IISProcess.PriorityClass != ProcessPriorityClass.Normal && IISControllerProvider.IISProcess.PriorityClass != ProcessPriorityClass.AboveNormal) - { - SetPriority(IISControllerProvider.IISProcess); - } - } - } - - private static void SetPriority(Process process) - { - Logger.Info("Updating [{0}] process priority from {1} to {2}", - process.ProcessName, - IISControllerProvider.IISProcess.PriorityClass, - ProcessPriorityClass.Normal); - process.PriorityClass = ProcessPriorityClass.Normal; - } - - - -#if DEBUG - private static void Attach() - { - if (Debugger.IsAttached) - { - Logger.Info("Trying to attach to debugger"); - - var count = 0; - - while (true) - { - try - { - ProcessAttacher.Attach(); - Logger.Info("Debugger Attached"); - return; - } - catch (Exception e) - { - count++; - if (count > 20) - { - Logger.WarnException("Unable to attach to debugger", e); - return; - } - - Thread.Sleep(100); - - } - } - } - } -#endif - - private static void AppDomainException(object excepion) - { - Console.WriteLine("EPIC FAIL: {0}", excepion); - Logger.Fatal("EPIC FAIL: {0}", excepion); - -#if RELEASE - new Client - { - ApiKey = "43BBF60A-EB2A-4C1C-B09E-422ADF637265", - ApplicationName = "NZBDrone", - CurrentException = excepion as Exception - }.Submit(); -#endif - - IISController.StopServer(); - } - - private static void ProgramExited(object sender, EventArgs e) - { - IISController.StopServer(); - } } } \ No newline at end of file diff --git a/NzbDrone/Providers/ConsoleProvider.cs b/NzbDrone/Providers/ConsoleProvider.cs new file mode 100644 index 000000000..886d636ff --- /dev/null +++ b/NzbDrone/Providers/ConsoleProvider.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Providers +{ + public class ConsoleProvider + { + public virtual void WaitForClose() + { + while (true) + { + Console.ReadLine(); + } + } + } +} diff --git a/NzbDrone/Providers/DebuggerProvider.cs b/NzbDrone/Providers/DebuggerProvider.cs new file mode 100644 index 000000000..28c6668aa --- /dev/null +++ b/NzbDrone/Providers/DebuggerProvider.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using NLog; + +namespace NzbDrone.Providers +{ + internal class DebuggerProvider + { + + private static readonly Logger Logger = LogManager.GetLogger("DebuggerProvider"); + + + internal virtual void Attach() + { +#if DEBUG + if (Debugger.IsAttached) + { + Logger.Info("Trying to attach to debugger"); + + var count = 0; + + while (true) + { + try + { + ProcessAttacher.Attach(); + Logger.Info("Debugger Attached"); + return; + } + catch (Exception e) + { + count++; + if (count > 20) + { + Logger.WarnException("Unable to attach to debugger", e); + return; + } + + Thread.Sleep(100); + + } + } + } +#endif + } + + + + } +} diff --git a/NzbDrone/Providers/IISControllerProvider.cs b/NzbDrone/Providers/IISProvider.cs similarity index 78% rename from NzbDrone/Providers/IISControllerProvider.cs rename to NzbDrone/Providers/IISProvider.cs index 844d7f006..d7335f676 100644 --- a/NzbDrone/Providers/IISControllerProvider.cs +++ b/NzbDrone/Providers/IISProvider.cs @@ -11,11 +11,11 @@ using NLog; namespace NzbDrone.Providers { - internal class IISControllerProvider + internal class IISProvider { private readonly ConfigProvider _configProvider; private static readonly Logger IISLogger = LogManager.GetLogger("IISExpress"); - private static readonly Logger Logger = LogManager.GetLogger("IISControllerProvider"); + private static readonly Logger Logger = LogManager.GetLogger("IISProvider"); private readonly string IISExe; private readonly string IISConfigPath; @@ -23,10 +23,10 @@ namespace NzbDrone.Providers private static Timer _pingTimer; private static int _pingFailCounter; - public static Process IISProcess { get; private set; } + private static Process _iisProcess; - public IISControllerProvider(ConfigProvider configProvider) + public IISProvider(ConfigProvider configProvider) { _configProvider = configProvider; IISExe = Path.Combine(_configProvider.IISFolder, @"iisexpress.exe"); @@ -38,27 +38,40 @@ namespace NzbDrone.Providers get { return string.Format("http://localhost:{0}/", _configProvider.Port); } } + internal int IISProcessId + { + get + { + if (_iisProcess == null) + { + throw new InvalidOperationException("IIS Process isn't running yet."); + } + + return _iisProcess.Id; + } + } + internal Process StartServer() { Logger.Info("Preparing IISExpress Server..."); - IISProcess = new Process(); + _iisProcess = new Process(); - IISProcess.StartInfo.FileName = IISExe; - IISProcess.StartInfo.Arguments = String.Format("/config:\"{0}\" /trace:i", IISConfigPath);//"/config:"""" /trace:i"; - IISProcess.StartInfo.WorkingDirectory = _configProvider.ApplicationRoot; + _iisProcess.StartInfo.FileName = IISExe; + _iisProcess.StartInfo.Arguments = String.Format("/config:\"{0}\" /trace:i", IISConfigPath);//"/config:"""" /trace:i"; + _iisProcess.StartInfo.WorkingDirectory = _configProvider.ApplicationRoot; - IISProcess.StartInfo.UseShellExecute = false; - IISProcess.StartInfo.RedirectStandardOutput = true; - IISProcess.StartInfo.RedirectStandardError = true; - IISProcess.StartInfo.CreateNoWindow = true; + _iisProcess.StartInfo.UseShellExecute = false; + _iisProcess.StartInfo.RedirectStandardOutput = true; + _iisProcess.StartInfo.RedirectStandardError = true; + _iisProcess.StartInfo.CreateNoWindow = true; - IISProcess.OutputDataReceived += (OnOutputDataReceived); - IISProcess.ErrorDataReceived += (OnErrorDataReceived); + _iisProcess.OutputDataReceived += (OnOutputDataReceived); + _iisProcess.ErrorDataReceived += (OnErrorDataReceived); //Set Variables for the config file. - IISProcess.StartInfo.EnvironmentVariables.Add("NZBDRONE_PATH", _configProvider.ApplicationRoot); - IISProcess.StartInfo.EnvironmentVariables.Add("NZBDRONE_PID", Process.GetCurrentProcess().Id.ToString()); + _iisProcess.StartInfo.EnvironmentVariables.Add("NZBDRONE_PATH", _configProvider.ApplicationRoot); + _iisProcess.StartInfo.EnvironmentVariables.Add("NZBDRONE_PID", Process.GetCurrentProcess().Id.ToString()); try { @@ -70,22 +83,22 @@ namespace NzbDrone.Providers } - Logger.Info("Starting process. [{0}]", IISProcess.StartInfo.FileName); + Logger.Info("Starting process. [{0}]", _iisProcess.StartInfo.FileName); - IISProcess.Start(); - IISProcess.PriorityClass = ProcessPriorityClass.AboveNormal; + _iisProcess.Start(); + _iisProcess.PriorityClass = ProcessPriorityClass.AboveNormal; - IISProcess.BeginErrorReadLine(); - IISProcess.BeginOutputReadLine(); + _iisProcess.BeginErrorReadLine(); + _iisProcess.BeginOutputReadLine(); //Start Ping _pingTimer = new Timer(300000) { AutoReset = true }; _pingTimer.Elapsed += (PingServer); _pingTimer.Start(); - return IISProcess; + return _iisProcess; } private static void OnErrorDataReceived(object sender, DataReceivedEventArgs e) @@ -98,7 +111,7 @@ namespace NzbDrone.Providers internal void StopServer() { - KillProcess(IISProcess); + KillProcess(_iisProcess); Logger.Info("Finding orphaned IIS Processes."); foreach (var process in Process.GetProcessesByName("IISExpress")) diff --git a/NzbDrone/Providers/ProcessProvider.cs b/NzbDrone/Providers/ProcessProvider.cs new file mode 100644 index 000000000..0f684c2a4 --- /dev/null +++ b/NzbDrone/Providers/ProcessProvider.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using NLog; + +namespace NzbDrone.Providers +{ + public class ProcessProvider + { + private static readonly Logger Logger = LogManager.GetLogger("ProcessProvider"); + + + public virtual void SetPriority(int processId, ProcessPriorityClass priority) + { + var process = Process.GetProcessById(processId); + + Logger.Info("Updating [{0}] process priority from {1} to {2}", + process.ProcessName, + process.PriorityClass, + priority); + + process.PriorityClass = priority; + } + + public virtual ProcessPriorityClass GetProcessPriority(int processId) + { + return Process.GetProcessById(processId).PriorityClass; + } + + public virtual int GetCurrentProcessId() + { + return Process.GetCurrentProcess().Id; + } + + public virtual Process Start(string path) + { + return Process.Start(path); + } + } +} diff --git a/NzbDrone/Providers/WebClientProvider.cs b/NzbDrone/Providers/WebClientProvider.cs new file mode 100644 index 000000000..d7a6bf2cd --- /dev/null +++ b/NzbDrone/Providers/WebClientProvider.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; + +namespace NzbDrone.Providers +{ + internal class WebClientProvider + { + + public virtual string DownloadString(string url) + { + return new WebClient().DownloadString(url); + } + } +} diff --git a/NzbDrone/packages.config b/NzbDrone/packages.config new file mode 100644 index 000000000..3d0555548 --- /dev/null +++ b/NzbDrone/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/packages/repositories.config b/packages/repositories.config index cfe66bd1b..c3ebed446 100644 --- a/packages/repositories.config +++ b/packages/repositories.config @@ -4,4 +4,5 @@ + \ No newline at end of file