using System; using System.Diagnostics; using System.IO; using NLog; using Ninject; using NzbDrone.Common; using NzbDrone.Common.Model; namespace NzbDrone.Providers { public class IISProvider { private static readonly Logger IISLogger = LogManager.GetLogger("Host.IISExpress"); private static readonly Logger Logger = LogManager.GetLogger("Host.IISProvider"); private readonly ConfigProvider _configProvider; private readonly ProcessProvider _processProvider; private readonly EnviromentProvider _enviromentProvider; [Inject] public IISProvider(ConfigProvider configProvider, ProcessProvider processProvider, EnviromentProvider enviromentProvider) { _configProvider = configProvider; _processProvider = processProvider; _enviromentProvider = enviromentProvider; } public IISProvider() { } public string AppUrl { get { return string.Format("http://localhost:{0}/", _configProvider.PortNumber); } } public int IISProcessId { get; private set; } public bool ServerStarted { get; private set; } public void StartServer() { Logger.Info("Preparing IISExpress Server..."); var startInfo = new ProcessStartInfo(); startInfo.FileName = _configProvider.IISExePath; startInfo.Arguments = String.Format("/config:\"{0}\" /trace:i", _configProvider.IISConfigPath); startInfo.WorkingDirectory = _enviromentProvider.ApplicationPath; startInfo.UseShellExecute = false; startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; startInfo.CreateNoWindow = true; //Set Variables for the config file. startInfo.EnvironmentVariables.Add("NZBDRONE_PATH", _enviromentProvider.ApplicationPath); startInfo.EnvironmentVariables.Add("NZBDRONE_PID", Process.GetCurrentProcess().Id.ToString()); try { _configProvider.UpdateIISConfig(_configProvider.IISConfigPath); } catch (Exception e) { Logger.ErrorException("An error has occurred while trying to update the config file.", e); } var iisProcess = _processProvider.Start(startInfo); IISProcessId = iisProcess.Id; iisProcess.OutputDataReceived += (OnOutputDataReceived); iisProcess.ErrorDataReceived += (OnErrorDataReceived); iisProcess.BeginErrorReadLine(); iisProcess.BeginOutputReadLine(); ServerStarted = true; } private static void OnErrorDataReceived(object sender, DataReceivedEventArgs e) { if (e == null || String.IsNullOrWhiteSpace(e.Data)) return; IISLogger.Error(e.Data); } public void StopServer() { _processProvider.Kill(IISProcessId); Logger.Info("Finding orphaned IIS Processes."); foreach (var process in _processProvider.GetProcessByName("IISExpress")) { Logger.Info("[{0}]IIS Process found. Path:{1}", process.Id, process.StartPath); if (NormalizePath(process.StartPath) == NormalizePath(_configProvider.IISExePath)) { Logger.Info("[{0}]Process is considered orphaned.", process.Id); _processProvider.Kill(process.Id); } else { Logger.Info("[{0}]Process has a different start-up path. skipping.", process.Id); } } } public void RestartServer() { ServerStarted = false; Logger.Warn("Attempting to restart server."); StopServer(); StartServer(); } private void OnOutputDataReceived(object s, DataReceivedEventArgs e) { if (e == null || String.IsNullOrWhiteSpace(e.Data) || e.Data.StartsWith("Request started:") || e.Data.StartsWith("Request ended:") || e.Data == ("IncrementMessages called")) return; //if (e.Data.Contains(" NzbDrone.")) { Console.WriteLine(e.Data); return; } IISLogger.Trace(e.Data); } private string NormalizePath(string path) { if (String.IsNullOrWhiteSpace(path)) throw new ArgumentException("Path can not be null or empty"); var info = new FileInfo(path); if (info.FullName.StartsWith(@"\\")) //UNC { return info.FullName.TrimEnd('/', '\\', ' '); } return info.FullName.Trim('/', '\\', ' ').ToLower(); } } }