From 9ba0e5283b2cc8fac97cc478310ad9d2b9cec712 Mon Sep 17 00:00:00 2001 From: Christian Nilsson Date: Thu, 15 Apr 2021 13:44:41 +0200 Subject: [PATCH 1/2] Allow service arguments, and non service mode Arguments can be used for configuration, so allow for them to exist Handling UserInteractive allows debugging without installing as service Signed-off-by: Christian Nilsson --- Service.cs | 52 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/Service.cs b/Service.cs index 19766eb..28a7c60 100644 --- a/Service.cs +++ b/Service.cs @@ -18,7 +18,7 @@ class OpenVpnService : System.ServiceProcess.ServiceBase public const string Package = "openvpn"; private List Subprocesses; - public OpenVpnService() + public OpenVpnService(string[] args) { this.ServiceName = DefaultServiceName; this.CanStop = true; @@ -30,11 +30,18 @@ public OpenVpnService() this.AutoLog = true; this.Subprocesses = new List(); + + // note, args in OnStart is only what is set as "start parameters" + // which is only used when manually starting the service and never saved } protected override void OnStop() { - RequestAdditionalTime(3000); + if (!Environment.UserInteractive) + { + // throws exception unless running as service + RequestAdditionalTime(3000); + } foreach (var child in Subprocesses) { child.SignalProcess(); @@ -179,15 +186,13 @@ private System.Diagnostics.ProcessPriorityClass GetPriorityClass(string priority public static int Main(string[] args) { - if (args.Length == 0) - { - Run(new OpenVpnService()); - } - else if (args[0] == "-install") + var arg0 = args.Length == 0 ? null : args[0]; + if (arg0 == "-install") { try { ProjectInstaller.Install(); + return 0; } catch (Exception e) { @@ -196,12 +201,13 @@ public static int Main(string[] args) return 1; } } - else if (args[0] == "-remove") + else if (arg0 == "-remove") { try { ProjectInstaller.Stop(); ProjectInstaller.Uninstall(); + return 0; } catch (Exception e) { @@ -212,10 +218,34 @@ public static int Main(string[] args) } else { - Console.Error.WriteLine("Unknown command: " + args[0]); - return 1; + var servicesToRun = new OpenVpnService[] + { + new OpenVpnService(args) + }; + + if (Environment.UserInteractive) + { + // if not started as service - we start it in debugable mode instead + foreach (var svc in servicesToRun) + { + // OnStart args is temporary, always use constructor instead + svc.OnStart(args); + } + + Console.WriteLine("Press enter to start shutdown"); + Console.ReadLine(); + + foreach (var svc in servicesToRun) + { + svc.OnStop(); + } + + return 0; + } + + Run(servicesToRun); + return 0; } - return 0; } } From ed6432a83ce756672ff84eeeb54db5b0e686acfb Mon Sep 17 00:00:00 2001 From: Christian Nilsson Date: Thu, 8 Apr 2021 00:34:05 +0200 Subject: [PATCH 2/2] Parse -BaseRegName argument which is used to override OpenVPN part of HKLM\Software\OpenVPN reg path Used to configure service to use HKLM\Software\MyNameVPN as configuration root. Allowing for multiple freestanding instances of openvpn service to coexist on the same system Also simpler handling on registry key enumeration via Linq Signed-off-by: Christian Nilsson --- Service.cs | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/Service.cs b/Service.cs index 28a7c60..7da6392 100644 --- a/Service.cs +++ b/Service.cs @@ -33,6 +33,7 @@ public OpenVpnService(string[] args) // note, args in OnStart is only what is set as "start parameters" // which is only used when manually starting the service and never saved + ParseArgs(args); } protected override void OnStop() @@ -55,12 +56,14 @@ protected override void OnStop() } } + private string ServiceBaseName = "OpenVPN"; + private RegistryKey GetRegistrySubkey(RegistryView rView) { try { return RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, rView) - .OpenSubKey("Software\\OpenVPN"); + .OpenSubKey(@"Software\\" + ServiceBaseName); } catch (ArgumentException) { @@ -72,19 +75,32 @@ private RegistryKey GetRegistrySubkey(RegistryView rView) } } + private void ParseArgs(string[] args) + { + string prevArg = null; + foreach (var arg in args) + { + var curPrev = prevArg; + prevArg = arg; + switch(curPrev) + { + case "-BaseRegName": + ServiceBaseName = arg; + break; + } + } + } + protected override void OnStart(string[] args) { try { - List rkOvpns = new List(); - // Search 64-bit registry, then 32-bit registry for OpenVpn - var key = GetRegistrySubkey(RegistryView.Registry64); - if (key != null) rkOvpns.Add(key); - key = GetRegistrySubkey(RegistryView.Registry32); - if (key != null) rkOvpns.Add(key); + var rkOvpns = (new[] { RegistryView.Registry64, RegistryView.Registry32 }) + .Select(GetRegistrySubkey) + .Where(k => k != null).ToList(); - if (rkOvpns.Count() == 0) + if (rkOvpns.Count == 0) throw new Exception("Registry key missing"); var configDirsConsidered = new HashSet(); @@ -154,7 +170,7 @@ protected override void OnStart(string[] args) catch (Exception e) { EventLog.WriteEntry("Exception occured during OpenVPN service start: " + e.Message + e.StackTrace); - throw e; + throw; } }