diff --git a/src/Tgstation.Server.Host.Service/Program.cs b/src/Tgstation.Server.Host.Service/Program.cs index 2bbb97239c..21123e7288 100644 --- a/src/Tgstation.Server.Host.Service/Program.cs +++ b/src/Tgstation.Server.Host.Service/Program.cs @@ -1,4 +1,13 @@ -using System.Diagnostics.CodeAnalysis; +using McMaster.Extensions.CommandLineUtils; +using System; +using System.Collections.Specialized; +using System.Configuration.Install; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Security.Principal; using System.ServiceProcess; using Tgstation.Server.Host.Watchdog; @@ -7,12 +16,94 @@ namespace Tgstation.Server.Host.Service /// /// Contains the entrypoint for the application /// - static class Program + [ExcludeFromCodeCoverage] + class Program { + /// + /// The --uninstall or -u option + /// + [Option(ShortName = "u")] + public bool Uninstall { get; } + + /// + /// The --install or -i option + /// + [Option(ShortName = "i")] + public bool Install { get; } + + /// + /// Check if the running user is a system administrator + /// + /// if the running user is a system administrator, otherwise + static bool IsAdministrator() + { + var user = WindowsIdentity.GetCurrent(); + var principal = new WindowsPrincipal(user); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } + + /// + /// Command line handler, always runs + /// + public void OnExecute() + { + if((Install || Uninstall) && !IsAdministrator()) + { + //try to restart as admin + var currentProcess = Process.GetCurrentProcess(); + var argList = Environment.GetCommandLineArgs().ToList(); + //its windows, first arg is .exe name guaranteed + var exe = argList.First(); + argList.RemoveAt(0); + var startInfo = new ProcessStartInfo + { + UseShellExecute = true, + Verb = "runas", + Arguments = String.Join(" ", argList), + FileName = Assembly.GetExecutingAssembly().Location, + WorkingDirectory = Environment.CurrentDirectory, + }; + using (Process.Start(startInfo)) + return; + } + + if (Install) + { + if (Uninstall) + //oh no, it's retarded... + return; + using (var processInstaller = new ServiceProcessInstaller()) + using (var installer = new ServiceInstaller()) + { + processInstaller.Account = ServiceAccount.NetworkService; + + installer.Context = new InstallContext("tgs-4-install.log", new string[] { String.Format(CultureInfo.InvariantCulture, "/assemblypath={0}", Assembly.GetEntryAssembly().Location) }); + installer.Description = "/tg/station 13 server v4 running as a windows service"; + installer.DisplayName = "/tg/station server 4"; + installer.DelayedAutoStart = true; + installer.StartType = ServiceStartMode.Automatic; + installer.ServicesDependedOn = new string[] { "Tcpip", "Dhcp", "Dnscache" }; + installer.ServiceName = ServerService.Name; + installer.Parent = processInstaller; + + var state = new ListDictionary(); + installer.Install(state); + } + } + else if (Uninstall) + using (var installer = new ServiceInstaller()) + { + installer.Context = new InstallContext("tgs-4-uninstall.log", null); + installer.ServiceName = ServerService.Name; + installer.Uninstall(null); + } + else + ServiceBase.Run(new ServerService(new WatchdogFactory())); + } + /// /// Entrypoint for the application /// - [ExcludeFromCodeCoverage] - static void Main() => ServiceBase.Run(new ServerService(new WatchdogFactory())); + static int Main(string[] args) => CommandLineApplication.Execute(args); } } diff --git a/src/Tgstation.Server.Host.Service/ServerService.cs b/src/Tgstation.Server.Host.Service/ServerService.cs index c7aad011cf..1242ea88fc 100644 --- a/src/Tgstation.Server.Host.Service/ServerService.cs +++ b/src/Tgstation.Server.Host.Service/ServerService.cs @@ -12,6 +12,11 @@ namespace Tgstation.Server.Host.Service /// sealed class ServerService : ServiceBase { + /// + /// The canonical windows service name + /// + public const string Name = "tgstation-server-4"; + /// /// The for the /// @@ -35,7 +40,7 @@ namespace Tgstation.Server.Host.Service { if (watchdogFactory == null) throw new ArgumentNullException(nameof(watchdogFactory)); - ServiceName = "tgstation-server"; + ServiceName = Name; watchdog = watchdogFactory.CreateWatchdog(); } diff --git a/src/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.csproj b/src/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.csproj index 530e071d08..2ea140835e 100644 --- a/src/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.csproj +++ b/src/Tgstation.Server.Host.Service/Tgstation.Server.Host.Service.csproj @@ -57,6 +57,7 @@ Tgstation.Server.Host.Service.Program + @@ -87,5 +88,10 @@ Tgstation.Server.Host.Watchdog + + + 2.2.4 + + \ No newline at end of file