Jackett/src/Jackett.Tray/Main.cs

313 lines
11 KiB
C#

using Jackett.Common.Models.Config;
using Jackett.Common.Services;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using NLog;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Jackett.Tray
{
public partial class Main : Form
{
private IProcessService processService;
private IServiceConfigService windowsService;
private ITrayLockService trayLockService;
private ISerializeService serializeService;
private IConfigurationService configurationService;
private ServerConfig serverConfig;
private Process consoleProcess;
private Logger logger;
private bool closeApplicationInitiated;
public Main(string updatedVersion)
{
Hide();
InitializeComponent();
Opacity = 0;
Enabled = false;
WindowState = FormWindowState.Minimized;
FormBorderStyle = FormBorderStyle.FixedToolWindow;
RuntimeSettings runtimeSettings = new RuntimeSettings()
{
CustomLogFileName = "TrayLog.txt"
};
LogManager.Configuration = LoggingSetup.GetLoggingConfiguration(runtimeSettings);
logger = LogManager.GetCurrentClassLogger();
logger.Info("Starting Jackett Tray v" + EnvironmentUtil.JackettVersion);
processService = new ProcessService(logger);
windowsService = new WindowsServiceConfigService(processService, logger);
trayLockService = new TrayLockService();
serializeService = new SerializeService();
configurationService = new ConfigurationService(serializeService, processService, logger, runtimeSettings);
serverConfig = configurationService.BuildServerConfig(runtimeSettings);
toolStripMenuItemAutoStart.Checked = AutoStart;
toolStripMenuItemAutoStart.CheckedChanged += toolStripMenuItemAutoStart_CheckedChanged;
toolStripMenuItemWebUI.Click += toolStripMenuItemWebUI_Click;
toolStripMenuItemShutdown.Click += toolStripMenuItemShutdown_Click;
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
toolStripMenuItemAutoStart.Visible = true;
}
if (!windowsService.ServiceExists())
{
// We are not installed as a service so just start the web server via JackettConsole and run from the tray.
logger.Info("Starting server from tray");
StartConsoleApplication();
}
updatedVersion = updatedVersion.Equals("yes", StringComparison.OrdinalIgnoreCase) ? EnvironmentUtil.JackettVersion : updatedVersion;
if (!string.IsNullOrWhiteSpace(updatedVersion))
{
notifyIcon1.BalloonTipTitle = "Jackett";
notifyIcon1.BalloonTipText = $"Jackett has updated to version {updatedVersion}";
notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
notifyIcon1.ShowBalloonTip(10000);
logger.Info($"Display balloon tip, updated to {updatedVersion}");
}
Task.Factory.StartNew(WaitForEvent);
}
private void WaitForEvent()
{
trayLockService.WaitForSignal();
logger.Info("Received signal from tray lock service");
if (windowsService.ServiceExists() && windowsService.ServiceRunning())
{
//We won't be able to start the tray app up again from the updater, as when running via a windows service there is no interaction with the desktop
//Fire off a console process that will start the tray 20 seconds later
string trayExePath = Assembly.GetEntryAssembly().Location;
var startInfo = new ProcessStartInfo()
{
Arguments = $"/c timeout 20 > NUL & \"{trayExePath}\" --UpdatedVersion yes",
FileName = "cmd.exe",
UseShellExecute = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
logger.Info("Starting 20 second delay tray launch as Jackett is running as a Windows service: " + startInfo.FileName + " " + startInfo.Arguments);
Process.Start(startInfo);
}
CloseTrayApplication();
}
private void toolStripMenuItemWebUI_Click(object sender, EventArgs e)
{
Process.Start("http://127.0.0.1:" + serverConfig.Port);
}
private void toolStripMenuItemShutdown_Click(object sender, EventArgs e)
{
CloseTrayApplication();
}
private void toolStripMenuItemAutoStart_CheckedChanged(object sender, EventArgs e)
{
AutoStart = toolStripMenuItemAutoStart.Checked;
}
private string ProgramTitle
{
get
{
return Assembly.GetExecutingAssembly().GetName().Name;
}
}
private bool AutoStart
{
get
{
return File.Exists(ShortcutPath);
}
set
{
if (value && !AutoStart)
{
CreateShortcut();
}
else if (!value && AutoStart)
{
File.Delete(ShortcutPath);
}
}
}
public string ShortcutPath
{
get
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), "Jackett.lnk");
}
}
private void CreateShortcut()
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
var appPath = Assembly.GetExecutingAssembly().Location;
var shell = new IWshRuntimeLibrary.WshShell();
var shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(ShortcutPath);
shortcut.Description = Assembly.GetExecutingAssembly().GetName().Name;
shortcut.TargetPath = appPath;
shortcut.Save();
}
}
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
if (windowsService.ServiceExists())
{
backgroundMenuItem.Visible = true;
serviceControlMenuItem.Visible = true;
toolStripSeparator1.Visible = true;
toolStripSeparator2.Visible = true;
if (windowsService.ServiceRunning())
{
serviceControlMenuItem.Text = "Stop background service";
backgroundMenuItem.Text = "Jackett is running as a background service";
toolStripMenuItemWebUI.Enabled = true;
}
else
{
serviceControlMenuItem.Text = "Start background service";
backgroundMenuItem.Text = "Jackett will run as a background service";
toolStripMenuItemWebUI.Enabled = false;
}
toolStripMenuItemShutdown.Text = "Close tray icon";
}
else
{
backgroundMenuItem.Visible = false;
serviceControlMenuItem.Visible = false;
toolStripSeparator1.Visible = false;
toolStripSeparator2.Visible = false;
toolStripMenuItemShutdown.Text = "Shutdown";
}
}
private void serviceControlMenuItem_Click(object sender, EventArgs e)
{
var consolePath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "JackettConsole.exe");
if (windowsService.ServiceRunning())
{
if (ServerUtil.IsUserAdministrator())
{
windowsService.Stop();
}
else
{
try
{
processService.StartProcessAndLog(consolePath, "--Stop", true);
}
catch
{
MessageBox.Show("Failed to get admin rights to stop the service.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
else
{
if (ServerUtil.IsUserAdministrator())
{
windowsService.Start();
}
else
{
try
{
processService.StartProcessAndLog(consolePath, "--Start", true);
}
catch
{
MessageBox.Show("Failed to get admin rights to start the service.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
private void CloseTrayApplication()
{
closeApplicationInitiated = true;
logger.Info("Close of tray application initiated");
//Clears notify icon, otherwise icon will still appear on taskbar until you hover the mouse over
notifyIcon1.Icon = null;
notifyIcon1.Dispose();
Application.DoEvents();
if (consoleProcess != null && !consoleProcess.HasExited)
{
consoleProcess.StandardInput.Close();
System.Threading.Thread.Sleep(1000);
if (consoleProcess != null && !consoleProcess.HasExited)
{
consoleProcess.Kill();
}
}
Application.Exit();
}
private void StartConsoleApplication()
{
string applicationFolder = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath);
var exePath = Path.Combine(applicationFolder, "JackettConsole.exe");
var startInfo = new ProcessStartInfo()
{
CreateNoWindow = true,
UseShellExecute = false,
FileName = exePath,
RedirectStandardInput = true,
RedirectStandardError = true
};
consoleProcess = Process.Start(startInfo);
consoleProcess.EnableRaisingEvents = true;
consoleProcess.Exited += ProcessExited;
consoleProcess.ErrorDataReceived += ProcessErrorDataReceived;
}
private void ProcessErrorDataReceived(object sender, DataReceivedEventArgs e)
{
logger.Error(e.Data);
}
private void ProcessExited(object sender, EventArgs e)
{
if (!closeApplicationInitiated)
{
logger.Info("Tray icon not responsible for process exit");
CloseTrayApplication();
}
}
}
}