diff --git a/src/Jackett.Common/Jackett.Common.csproj b/src/Jackett.Common/Jackett.Common.csproj index 32a8a4d68..c49fbccad 100644 --- a/src/Jackett.Common/Jackett.Common.csproj +++ b/src/Jackett.Common/Jackett.Common.csproj @@ -193,6 +193,7 @@ + @@ -208,6 +209,9 @@ 2.0.0 + + 4.5.0 + diff --git a/src/Jackett.Common/Services/WindowsServiceConfigService.cs b/src/Jackett.Common/Services/WindowsServiceConfigService.cs new file mode 100644 index 000000000..0fec4f3dc --- /dev/null +++ b/src/Jackett.Common/Services/WindowsServiceConfigService.cs @@ -0,0 +1,119 @@ +using Jackett.Common.Services.Interfaces; +using NLog; +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.ServiceProcess; + +namespace Jackett.Common.Services +{ + public class WindowsServiceConfigService : IServiceConfigService + { + private const string NAME = "Jackett"; + private const string DESCRIPTION = "API Support for your favorite torrent trackers"; + private const string SERVICEEXE = "JackettService.exe"; + + private IProcessService processService; + private Logger logger; + + public WindowsServiceConfigService(IProcessService p, Logger l) + { + processService = p; + logger = l; + } + + public bool ServiceExists() + { + return GetService(NAME) != null; + } + + public bool ServiceRunning() + { + var service = GetService(NAME); + if (service == null) + return false; + return service.Status == ServiceControllerStatus.Running; + } + + public void Start() + { + var service = GetService(NAME); + service.Start(); + } + + public void Stop() + { + var service = GetService(NAME); + service.Stop(); + } + + public ServiceController GetService(string serviceName) + { + return ServiceController.GetServices().FirstOrDefault(c => String.Equals(c.ServiceName, serviceName, StringComparison.InvariantCultureIgnoreCase)); + } + + public void Install() + { + if (ServiceExists()) + { + logger.Warn("The service is already installed!"); + } + else + { + string applicationFolder = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath); + + var exePath = Path.Combine(applicationFolder, SERVICEEXE); + if (!File.Exists(exePath) && Debugger.IsAttached) + { + exePath = Path.Combine(applicationFolder, "..\\..\\..\\Jackett.Service\\bin\\Debug", SERVICEEXE); + } + + string arg = $"create {NAME} start= auto binpath= \"{exePath}\" DisplayName= {NAME}"; + + processService.StartProcessAndLog("sc.exe", arg, true); + + processService.StartProcessAndLog("sc.exe", $"description {NAME} \"{DESCRIPTION}\"", true); + } + } + + public void Uninstall() + { + RemoveService(); + + processService.StartProcessAndLog("sc.exe", $"delete {NAME}", true); + + logger.Info("The service was uninstalled."); + } + + public void RemoveService() + { + var service = GetService(NAME); + if (service == null) + { + logger.Warn("The service is already uninstalled"); + return; + } + if (service.Status != ServiceControllerStatus.Stopped) + { + service.Stop(); + service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60)); + + service.Refresh(); + if (service.Status == ServiceControllerStatus.Stopped) + { + logger.Info("Service stopped."); + } + else + { + logger.Error("Failed to stop the service"); + } + } + else + { + logger.Warn("The service was already stopped"); + } + } + } +} diff --git a/src/Jackett.Common/Utils/LoggingSetup.cs b/src/Jackett.Common/Utils/LoggingSetup.cs new file mode 100644 index 000000000..e73a5ecf8 --- /dev/null +++ b/src/Jackett.Common/Utils/LoggingSetup.cs @@ -0,0 +1,49 @@ +using Jackett.Common.Models.Config; +using Jackett.Common.Services; +using NLog.Config; +using NLog.Targets; +using System.IO; + +namespace Jackett.Common.Utils +{ + public static class LoggingSetup + { + public static LoggingConfiguration GetLoggingConfiguration(RuntimeSettings settings, bool fileOnly = false) + { + var logFileName = settings.CustomLogFileName ?? "log.txt"; + var logLevel = settings.TracingEnabled ? NLog.LogLevel.Debug : NLog.LogLevel.Info; + // Add custom date time format renderer as the default is too long + ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("simpledatetime", typeof(SimpleDateTimeRenderer)); + + var logConfig = new LoggingConfiguration(); + var logFile = new FileTarget(); + logConfig.AddTarget("file", logFile); + logFile.Layout = "${longdate} ${level} ${message} ${exception:format=ToString}"; + logFile.FileName = Path.Combine(settings.DataFolder, logFileName); + logFile.ArchiveFileName = Path.Combine(settings.DataFolder, logFileName + ".{#####}.txt"); + logFile.ArchiveAboveSize = 500000; + logFile.MaxArchiveFiles = 5; + logFile.KeepFileOpen = false; + logFile.ArchiveNumbering = ArchiveNumberingMode.DateAndSequence; + var logFileRule = new LoggingRule("*", logLevel, logFile); + logConfig.LoggingRules.Add(logFileRule); + + if (!fileOnly) + { + var logConsole = new ColoredConsoleTarget(); + logConfig.AddTarget("console", logConsole); + + logConsole.Layout = "${simpledatetime} ${level} ${message} ${exception:format=ToString}"; + var logConsoleRule = new LoggingRule("*", logLevel, logConsole); + logConfig.LoggingRules.Add(logConsoleRule); + + var logService = new LogCacheService(); + logConfig.AddTarget("service", logService); + var serviceRule = new LoggingRule("*", logLevel, logService); + logConfig.LoggingRules.Add(serviceRule); + } + + return logConfig; + } + } +}