From efc3e34f6db4f7cb8c16d22f0eb179461a177001 Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Fri, 31 Jul 2020 00:00:00 +0800 Subject: [PATCH] Refactor service configuration --- .../Configuration/DefaultSettings.cs | 90 ----------- .../Configuration/IWinSWConfiguration.cs | 76 ---------- src/WinSW.Core/Configuration/ServiceConfig.cs | 90 +++++++++++ .../XmlServiceConfig.cs} | 111 +++++++------- .../Extensions/AbstractWinSWExtension.cs | 2 +- src/WinSW.Core/Extensions/IWinSWExtension.cs | 4 +- .../Extensions/WinSWExtensionManager.cs | 12 +- .../RunawayProcessKillerExtension.cs | 4 +- src/WinSW.Plugins/SharedDirectoryMapper.cs | 5 +- src/WinSW.Tests/Configuration/ExamplesTest.cs | 20 +-- src/WinSW.Tests/DownloadConfigTests.cs | 52 +++---- .../Extensions/RunawayProcessKillerTest.cs | 14 +- .../SharedDirectoryMapperConfigTest.cs | 8 +- ...scriptorTests.cs => ServiceConfigTests.cs} | 129 ++++++++-------- src/WinSW.Tests/Util/CommandLineTestHelper.cs | 18 +-- src/WinSW.Tests/Util/ConfigXmlBuilder.cs | 4 +- src/WinSW.Tests/Util/ServiceConfigAssert.cs | 34 +++++ .../Util/ServiceDescriptorAssert.cs | 64 -------- src/WinSW/Program.cs | 142 +++++++++--------- src/WinSW/WrapperService.cs | 66 ++++---- 20 files changed, 415 insertions(+), 530 deletions(-) delete mode 100644 src/WinSW.Core/Configuration/DefaultSettings.cs delete mode 100644 src/WinSW.Core/Configuration/IWinSWConfiguration.cs create mode 100644 src/WinSW.Core/Configuration/ServiceConfig.cs rename src/WinSW.Core/{ServiceDescriptor.cs => Configuration/XmlServiceConfig.cs} (86%) rename src/WinSW.Tests/{ServiceDescriptorTests.cs => ServiceConfigTests.cs} (67%) create mode 100644 src/WinSW.Tests/Util/ServiceConfigAssert.cs delete mode 100644 src/WinSW.Tests/Util/ServiceDescriptorAssert.cs diff --git a/src/WinSW.Core/Configuration/DefaultSettings.cs b/src/WinSW.Core/Configuration/DefaultSettings.cs deleted file mode 100644 index 33a5f24..0000000 --- a/src/WinSW.Core/Configuration/DefaultSettings.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.ServiceProcess; -using System.Xml; - -namespace WinSW.Configuration -{ - /// - /// Default WinSW settings - /// - public sealed class DefaultWinSWSettings : IWinSWConfiguration - { - public string FullPath => throw new InvalidOperationException(nameof(this.FullPath) + " must be specified."); - - public string Id => throw new InvalidOperationException(nameof(this.Id) + " must be specified."); - - public string Caption => string.Empty; - - public string Description => string.Empty; - - public string Executable => throw new InvalidOperationException(nameof(this.Executable) + " must be specified."); - - public bool HideWindow => false; - - public string ExecutablePath => Process.GetCurrentProcess().MainModule.FileName; - - // Installation - public bool AllowServiceAcountLogonRight => false; - - public string? ServiceAccountPassword => null; - - public string? ServiceAccountUserName => null; - - public Native.SC_ACTION[] FailureActions => new Native.SC_ACTION[0]; - - public TimeSpan ResetFailureAfter => TimeSpan.FromDays(1); - - // Executable management - public string Arguments => string.Empty; - - public string? StartArguments => null; - - public string? StopExecutable => null; - - public string? StopArguments => null; - - public string WorkingDirectory => Path.GetDirectoryName(this.FullPath)!; - - public ProcessPriorityClass Priority => ProcessPriorityClass.Normal; - - public TimeSpan StopTimeout => TimeSpan.FromSeconds(15); - - // Service management - public ServiceStartMode StartMode => ServiceStartMode.Automatic; - - public bool DelayedAutoStart => false; - - public bool Preshutdown => false; - - public string[] ServiceDependencies => new string[0]; - - public bool Interactive => false; - - // Logging - public string LogDirectory => Path.GetDirectoryName(this.ExecutablePath)!; - - public string LogMode => "append"; - - public bool OutFileDisabled => false; - - public bool ErrFileDisabled => false; - - public string OutFilePattern => ".out.log"; - - public string ErrFilePattern => ".err.log"; - - // Environment - public List Downloads => new List(0); - - public Dictionary EnvironmentVariables => new Dictionary(0); - - // Misc - public bool BeepOnShutdown => false; - - // Extensions - public XmlNode? ExtensionsConfiguration => null; - } -} diff --git a/src/WinSW.Core/Configuration/IWinSWConfiguration.cs b/src/WinSW.Core/Configuration/IWinSWConfiguration.cs deleted file mode 100644 index 2d512f1..0000000 --- a/src/WinSW.Core/Configuration/IWinSWConfiguration.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.ServiceProcess; -using System.Xml; - -namespace WinSW.Configuration -{ - // TODO: Document the parameters && refactor - public interface IWinSWConfiguration - { - string FullPath { get; } - - string Id { get; } - - string Caption { get; } - - string Description { get; } - - string Executable { get; } - - string ExecutablePath { get; } - - bool HideWindow { get; } - - // Installation - bool AllowServiceAcountLogonRight { get; } - - string? ServiceAccountPassword { get; } - - string? ServiceAccountUserName { get; } - - Native.SC_ACTION[] FailureActions { get; } - - TimeSpan ResetFailureAfter { get; } - - // Executable management - string Arguments { get; } - - string? StartArguments { get; } - - string? StopExecutable { get; } - - string? StopArguments { get; } - - string WorkingDirectory { get; } - - ProcessPriorityClass Priority { get; } - - TimeSpan StopTimeout { get; } - - // Service management - ServiceStartMode StartMode { get; } - - string[] ServiceDependencies { get; } - - bool Interactive { get; } - - // Logging - string LogDirectory { get; } - - // TODO: replace by enum - string LogMode { get; } - - // Environment - List Downloads { get; } - - Dictionary EnvironmentVariables { get; } - - // Misc - bool BeepOnShutdown { get; } - - // Extensions - XmlNode? ExtensionsConfiguration { get; } - } -} diff --git a/src/WinSW.Core/Configuration/ServiceConfig.cs b/src/WinSW.Core/Configuration/ServiceConfig.cs new file mode 100644 index 0000000..397aee9 --- /dev/null +++ b/src/WinSW.Core/Configuration/ServiceConfig.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.ServiceProcess; +using System.Xml; + +namespace WinSW.Configuration +{ + /// + /// Default WinSW settings + /// + public abstract class ServiceConfig + { + public abstract string FullPath { get; } + + public abstract string Id { get; } + + public virtual string Caption => string.Empty; + + public virtual string Description => string.Empty; + + public abstract string Executable { get; } + + public string ExecutablePath => Process.GetCurrentProcess().MainModule.FileName; + + public virtual bool HideWindow => false; + + // Installation + public virtual bool AllowServiceAcountLogonRight => false; + + public virtual string? ServiceAccountPassword => null; + + public virtual string? ServiceAccountUserName => null; + + public virtual Native.SC_ACTION[] FailureActions => new Native.SC_ACTION[0]; + + public virtual TimeSpan ResetFailureAfter => TimeSpan.FromDays(1); + + // Executable management + public virtual string Arguments => string.Empty; + + public virtual string? StartArguments => null; + + public virtual string? StopExecutable => null; + + public virtual string? StopArguments => null; + + public virtual string WorkingDirectory => Path.GetDirectoryName(this.FullPath)!; + + public virtual ProcessPriorityClass Priority => ProcessPriorityClass.Normal; + + public virtual TimeSpan StopTimeout => TimeSpan.FromSeconds(15); + + // Service management + public virtual ServiceStartMode StartMode => ServiceStartMode.Automatic; + + public virtual string[] ServiceDependencies => new string[0]; + + public virtual bool Interactive => false; + + public virtual bool DelayedAutoStart => false; + + public virtual bool Preshutdown => false; + + // Logging + public virtual string LogDirectory => Path.GetDirectoryName(this.ExecutablePath)!; + + public virtual string LogMode => "append"; + + public virtual bool OutFileDisabled => false; + + public virtual bool ErrFileDisabled => false; + + public virtual string OutFilePattern => ".out.log"; + + public virtual string ErrFilePattern => ".err.log"; + + // Environment + public virtual List Downloads => new List(0); + + public virtual Dictionary EnvironmentVariables => new Dictionary(0); + + // Misc + public virtual bool BeepOnShutdown => false; + + // Extensions + public virtual XmlNode? ExtensionsConfiguration => null; + } +} diff --git a/src/WinSW.Core/ServiceDescriptor.cs b/src/WinSW.Core/Configuration/XmlServiceConfig.cs similarity index 86% rename from src/WinSW.Core/ServiceDescriptor.cs rename to src/WinSW.Core/Configuration/XmlServiceConfig.cs index fa04a24..2656f21 100644 --- a/src/WinSW.Core/ServiceDescriptor.cs +++ b/src/WinSW.Core/Configuration/XmlServiceConfig.cs @@ -15,17 +15,15 @@ namespace WinSW /// /// In-memory representation of the configuration file. /// - public class ServiceDescriptor : IWinSWConfiguration + public class XmlServiceConfig : ServiceConfig { protected readonly XmlDocument dom = new XmlDocument(); private readonly Dictionary environmentVariables; - internal static ServiceDescriptor? TestDescriptor; + internal static XmlServiceConfig? TestConfig; - public static DefaultWinSWSettings Defaults { get; } = new DefaultWinSWSettings(); - - public string FullPath { get; } + public override string FullPath { get; } /// /// Where did we find the configuration file? @@ -41,10 +39,7 @@ namespace WinSW /// public string BaseName { get; set; } - // Currently there is no opportunity to alter the executable path - public virtual string ExecutablePath => Defaults.ExecutablePath; - - public ServiceDescriptor() + public XmlServiceConfig() { string path = this.ExecutablePath; string baseName = Path.GetFileNameWithoutExtension(path); @@ -84,7 +79,7 @@ namespace WinSW } /// - public ServiceDescriptor(string path) + public XmlServiceConfig(string path) { if (!File.Exists(path)) { @@ -122,10 +117,10 @@ namespace WinSW } /// - /// Loads descriptor from existing DOM + /// Loads config from existing DOM /// #pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. - public ServiceDescriptor(XmlDocument dom) + public XmlServiceConfig(XmlDocument dom) #pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. { this.dom = dom; @@ -133,16 +128,16 @@ namespace WinSW this.environmentVariables = this.LoadEnvironmentVariables(); } - internal static ServiceDescriptor Create(string? path) + internal static XmlServiceConfig Create(string? path) { - return path != null ? new ServiceDescriptor(path) : TestDescriptor ?? new ServiceDescriptor(); + return path != null ? new XmlServiceConfig(path) : TestConfig ?? new XmlServiceConfig(); } - public static ServiceDescriptor FromXml(string xml) + public static XmlServiceConfig FromXml(string xml) { var dom = new XmlDocument(); dom.LoadXml(xml); - return new ServiceDescriptor(dom); + return new XmlServiceConfig(dom); } private string SingleElement(string tagName) @@ -213,31 +208,31 @@ namespace WinSW /// /// Path to the executable. /// - public string Executable => this.SingleElement("executable"); + public override string Executable => this.SingleElement("executable"); - public bool HideWindow => this.SingleBoolElement("hidewindow", Defaults.HideWindow); + public override bool HideWindow => this.SingleBoolElement("hidewindow", base.HideWindow); /// /// Optionally specify a different Path to an executable to shutdown the service. /// - public string? StopExecutable => this.SingleElement("stopexecutable", true); + public override string? StopExecutable => this.SingleElement("stopexecutable", true); /// /// The arguments element. /// - public string Arguments + public override string Arguments { get { XmlNode? argumentsNode = this.dom.SelectSingleNode("//arguments"); - return argumentsNode is null ? Defaults.Arguments : Environment.ExpandEnvironmentVariables(argumentsNode.InnerText); + return argumentsNode is null ? base.Arguments : Environment.ExpandEnvironmentVariables(argumentsNode.InnerText); } } /// /// The startarguments element. /// - public string? StartArguments + public override string? StartArguments { get { @@ -249,7 +244,7 @@ namespace WinSW /// /// The stoparguments element. /// - public string? StopArguments + public override string? StopArguments { get { @@ -274,12 +269,12 @@ namespace WinSW public string? PoststopArguments => this.GetArguments(Names.Poststop); - public string WorkingDirectory + public override string WorkingDirectory { get { var wd = this.SingleElement("workingdirectory", true); - return string.IsNullOrEmpty(wd) ? Defaults.WorkingDirectory : wd!; + return string.IsNullOrEmpty(wd) ? base.WorkingDirectory : wd!; } } @@ -304,7 +299,7 @@ namespace WinSW } } - public XmlNode? ExtensionsConfiguration => this.dom.SelectSingleNode("//extensions"); + public override XmlNode? ExtensionsConfiguration => this.dom.SelectSingleNode("//extensions"); /// /// Combines the contents of all the elements of the given name, @@ -351,19 +346,19 @@ namespace WinSW /// /// LogDirectory is the service wrapper executable directory or the optionally specified logpath element. /// - public string LogDirectory + public override string LogDirectory { get { XmlNode? loggingNode = this.dom.SelectSingleNode("//logpath"); return loggingNode is null - ? Defaults.LogDirectory + ? base.LogDirectory : Environment.ExpandEnvironmentVariables(loggingNode.InnerText); } } - public string LogMode + public override string LogMode { get { @@ -385,7 +380,7 @@ namespace WinSW } } - return mode ?? Defaults.LogMode; + return mode ?? base.LogMode; } } @@ -399,27 +394,27 @@ namespace WinSW } } - public bool OutFileDisabled => this.SingleBoolElement("outfiledisabled", Defaults.OutFileDisabled); + public override bool OutFileDisabled => this.SingleBoolElement("outfiledisabled", base.OutFileDisabled); - public bool ErrFileDisabled => this.SingleBoolElement("errfiledisabled", Defaults.ErrFileDisabled); + public override bool ErrFileDisabled => this.SingleBoolElement("errfiledisabled", base.ErrFileDisabled); - public string OutFilePattern + public override string OutFilePattern { get { XmlNode? loggingName = this.dom.SelectSingleNode("//outfilepattern"); - return loggingName is null ? Defaults.OutFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText); + return loggingName is null ? base.OutFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText); } } - public string ErrFilePattern + public override string ErrFilePattern { get { XmlNode? loggingName = this.dom.SelectSingleNode("//errfilepattern"); - return loggingName is null ? Defaults.ErrFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText); + return loggingName is null ? base.ErrFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText); } } @@ -514,14 +509,14 @@ namespace WinSW /// /// Optionally specified depend services that must start before this service starts. /// - public string[] ServiceDependencies + public override string[] ServiceDependencies { get { XmlNodeList? nodeList = this.dom.SelectNodes("//depend"); if (nodeList is null) { - return Defaults.ServiceDependencies; + return base.ServiceDependencies; } string[] serviceDependencies = new string[nodeList.Count]; @@ -534,23 +529,23 @@ namespace WinSW } } - public string Id => this.SingleElement("id"); + public override string Id => this.SingleElement("id"); - public string Caption => this.SingleElement("name", true) ?? Defaults.Caption; + public override string Caption => this.SingleElement("name", true) ?? base.Caption; - public string Description => this.SingleElement("description", true) ?? Defaults.Description; + public override string Description => this.SingleElement("description", true) ?? base.Description; /// /// Start mode of the Service /// - public ServiceStartMode StartMode + public override ServiceStartMode StartMode { get { string? p = this.SingleElement("startmode", true); if (p is null) { - return Defaults.StartMode; + return base.StartMode; } try @@ -575,9 +570,9 @@ namespace WinSW /// True if the service should be installed with the DelayedAutoStart flag. /// This setting will be applyed only during the install command and only when the Automatic start mode is configured. /// - public bool DelayedAutoStart => this.SingleBoolElement("delayedAutoStart", Defaults.DelayedAutoStart); + public override bool DelayedAutoStart => this.SingleBoolElement("delayedAutoStart", base.DelayedAutoStart); - public bool Preshutdown => this.SingleBoolElement("preshutdown", Defaults.Preshutdown); + public override bool Preshutdown => this.SingleBoolElement("preshutdown", base.Preshutdown); public TimeSpan? PreshutdownTimeout { @@ -592,30 +587,30 @@ namespace WinSW /// True if the service should beep when finished on shutdown. /// This doesn't work on some OSes. See http://msdn.microsoft.com/en-us/library/ms679277%28VS.85%29.aspx /// - public bool BeepOnShutdown => this.SingleBoolElement("beeponshutdown", Defaults.DelayedAutoStart); + public override bool BeepOnShutdown => this.SingleBoolElement("beeponshutdown", base.DelayedAutoStart); /// /// True if the service can interact with the desktop. /// - public bool Interactive => this.SingleBoolElement("interactive", Defaults.DelayedAutoStart); + public override bool Interactive => this.SingleBoolElement("interactive", base.DelayedAutoStart); /// /// Environment variable overrides /// - public Dictionary EnvironmentVariables => new Dictionary(this.environmentVariables); + public override Dictionary EnvironmentVariables => new Dictionary(this.environmentVariables); /// /// List of downloads to be performed by the wrapper before starting /// a service. /// - public List Downloads + public override List Downloads { get { XmlNodeList? nodeList = this.dom.SelectNodes("//download"); if (nodeList is null) { - return Defaults.Downloads; + return base.Downloads; } List result = new List(nodeList.Count); @@ -631,7 +626,7 @@ namespace WinSW } } - public SC_ACTION[] FailureActions + public override SC_ACTION[] FailureActions { get { @@ -661,7 +656,7 @@ namespace WinSW } } - public TimeSpan ResetFailureAfter => this.SingleTimeSpanElement(this.dom, "resetfailure", Defaults.ResetFailureAfter); + public override TimeSpan ResetFailureAfter => this.SingleTimeSpanElement(this.dom, "resetfailure", base.ResetFailureAfter); protected string? GetServiceAccountPart(string subNodeName) { @@ -683,16 +678,16 @@ namespace WinSW protected string? AllowServiceLogon => this.GetServiceAccountPart("allowservicelogon"); - public string? ServiceAccountPassword => this.GetServiceAccountPart("password"); + public override string? ServiceAccountPassword => this.GetServiceAccountPart("password"); - public string? ServiceAccountUserName => this.GetServiceAccountPart("username"); + public override string? ServiceAccountUserName => this.GetServiceAccountPart("username"); public bool HasServiceAccount() { return this.dom.SelectSingleNode("//serviceaccount") != null; } - public bool AllowServiceAcountLogonRight + public override bool AllowServiceAcountLogonRight { get { @@ -711,19 +706,19 @@ namespace WinSW /// /// Time to wait for the service to gracefully shutdown the executable before we forcibly kill it /// - public TimeSpan StopTimeout => this.SingleTimeSpanElement(this.dom, "stoptimeout", Defaults.StopTimeout); + public override TimeSpan StopTimeout => this.SingleTimeSpanElement(this.dom, "stoptimeout", base.StopTimeout); /// /// Desired process priority or null if not specified. /// - public ProcessPriorityClass Priority + public override ProcessPriorityClass Priority { get { string? p = this.SingleElement("priority", true); if (p is null) { - return Defaults.Priority; + return base.Priority; } return (ProcessPriorityClass)Enum.Parse(typeof(ProcessPriorityClass), p, true); diff --git a/src/WinSW.Core/Extensions/AbstractWinSWExtension.cs b/src/WinSW.Core/Extensions/AbstractWinSWExtension.cs index bfc5f4a..691d641 100644 --- a/src/WinSW.Core/Extensions/AbstractWinSWExtension.cs +++ b/src/WinSW.Core/Extensions/AbstractWinSWExtension.cs @@ -10,7 +10,7 @@ namespace WinSW.Extensions public WinSWExtensionDescriptor Descriptor { get; set; } #pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. - public virtual void Configure(ServiceDescriptor descriptor, XmlNode node) + public virtual void Configure(XmlServiceConfig config, XmlNode node) { // Do nothing } diff --git a/src/WinSW.Core/Extensions/IWinSWExtension.cs b/src/WinSW.Core/Extensions/IWinSWExtension.cs index a7c1f35..2240367 100644 --- a/src/WinSW.Core/Extensions/IWinSWExtension.cs +++ b/src/WinSW.Core/Extensions/IWinSWExtension.cs @@ -25,9 +25,9 @@ namespace WinSW.Extensions /// /// Init handler. Extension should load it's config during that step /// - /// Service descriptor + /// Service config /// Configuration node - void Configure(ServiceDescriptor descriptor, XmlNode node); + void Configure(XmlServiceConfig config, XmlNode node); /// /// Start handler. Called during startup of the service before the child process. diff --git a/src/WinSW.Core/Extensions/WinSWExtensionManager.cs b/src/WinSW.Core/Extensions/WinSWExtensionManager.cs index 1ecb90b..1b629ea 100644 --- a/src/WinSW.Core/Extensions/WinSWExtensionManager.cs +++ b/src/WinSW.Core/Extensions/WinSWExtensionManager.cs @@ -9,13 +9,13 @@ namespace WinSW.Extensions { public Dictionary Extensions { get; } - public ServiceDescriptor ServiceDescriptor { get; } + public XmlServiceConfig ServiceConfig { get; } private static readonly ILog Log = LogManager.GetLogger(typeof(WinSWExtensionManager)); - public WinSWExtensionManager(ServiceDescriptor serviceDescriptor) + public WinSWExtensionManager(XmlServiceConfig serviceConfig) { - this.ServiceDescriptor = serviceDescriptor; + this.ServiceConfig = serviceConfig; this.Extensions = new Dictionary(); } @@ -107,7 +107,7 @@ namespace WinSW.Extensions /// Loading failure public void LoadExtensions() { - var extensionIds = this.ServiceDescriptor.ExtensionIds; + var extensionIds = this.ServiceConfig.ExtensionIds; foreach (string extensionId in extensionIds) { this.LoadExtension(extensionId); @@ -127,7 +127,7 @@ namespace WinSW.Extensions throw new ExtensionException(id, "Extension has been already loaded"); } - XmlNode? extensionsConfig = this.ServiceDescriptor.ExtensionsConfiguration; + XmlNode? extensionsConfig = this.ServiceConfig.ExtensionsConfiguration; XmlElement? configNode = extensionsConfig is null ? null : extensionsConfig.SelectSingleNode("extension[@id='" + id + "'][1]") as XmlElement; if (configNode is null) { @@ -141,7 +141,7 @@ namespace WinSW.Extensions extension.Descriptor = descriptor; try { - extension.Configure(this.ServiceDescriptor, configNode); + extension.Configure(this.ServiceConfig, configNode); } catch (Exception ex) { // Consider any unexpected exception as fatal diff --git a/src/WinSW.Plugins/RunawayProcessKillerExtension.cs b/src/WinSW.Plugins/RunawayProcessKillerExtension.cs index ee1bb01..474a379 100644 --- a/src/WinSW.Plugins/RunawayProcessKillerExtension.cs +++ b/src/WinSW.Plugins/RunawayProcessKillerExtension.cs @@ -173,13 +173,13 @@ namespace WinSW.Plugins.RunawayProcessKiller return parameters.Environment; } - public override void Configure(ServiceDescriptor descriptor, XmlNode node) + public override void Configure(XmlServiceConfig config, XmlNode node) { // We expect the upper logic to process any errors // TODO: a better parser API for types would be useful this.Pidfile = XmlHelper.SingleElement(node, "pidfile", false)!; this.StopTimeout = TimeSpan.FromMilliseconds(int.Parse(XmlHelper.SingleElement(node, "stopTimeout", false)!)); - this.ServiceId = descriptor.Id; + this.ServiceId = config.Id; // TODO: Consider making it documented var checkWinSWEnvironmentVariable = XmlHelper.SingleElement(node, "checkWinSWEnvironmentVariable", true); diff --git a/src/WinSW.Plugins/SharedDirectoryMapper.cs b/src/WinSW.Plugins/SharedDirectoryMapper.cs index df7f649..0fa1925 100644 --- a/src/WinSW.Plugins/SharedDirectoryMapper.cs +++ b/src/WinSW.Plugins/SharedDirectoryMapper.cs @@ -27,7 +27,7 @@ namespace WinSW.Plugins.SharedDirectoryMapper this.entries.Add(config); } - public override void Configure(ServiceDescriptor descriptor, XmlNode node) + public override void Configure(XmlServiceConfig config, XmlNode node) { XmlNodeList? mapNodes = XmlHelper.SingleNode(node, "mapping", false)!.SelectNodes("map"); if (mapNodes != null) @@ -36,8 +36,7 @@ namespace WinSW.Plugins.SharedDirectoryMapper { if (mapNodes[i] is XmlElement mapElement) { - var config = SharedDirectoryMapperConfig.FromXml(mapElement); - this.entries.Add(config); + this.entries.Add(SharedDirectoryMapperConfig.FromXml(mapElement)); } } } diff --git a/src/WinSW.Tests/Configuration/ExamplesTest.cs b/src/WinSW.Tests/Configuration/ExamplesTest.cs index 7e102fb..4e868c0 100644 --- a/src/WinSW.Tests/Configuration/ExamplesTest.cs +++ b/src/WinSW.Tests/Configuration/ExamplesTest.cs @@ -15,26 +15,26 @@ namespace WinSW.Tests.Configuration [Fact] public void AllOptionsConfigShouldDeclareDefaults() { - ServiceDescriptor desc = Load("complete"); + XmlServiceConfig config = Load("complete"); - Assert.Equal("myapp", desc.Id); - Assert.Equal("%BASE%\\myExecutable.exe", desc.Executable); + Assert.Equal("myapp", config.Id); + Assert.Equal("%BASE%\\myExecutable.exe", config.Executable); - ServiceDescriptorAssert.AssertAllOptionalPropertiesAreDefault(desc); + ServiceConfigAssert.AssertAllOptionalPropertiesAreDefault(config); } [Fact] public void MinimalConfigShouldDeclareDefaults() { - ServiceDescriptor desc = Load("minimal"); + XmlServiceConfig config = Load("minimal"); - Assert.Equal("myapp", desc.Id); - Assert.Equal("%BASE%\\myExecutable.exe", desc.Executable); + Assert.Equal("myapp", config.Id); + Assert.Equal("%BASE%\\myExecutable.exe", config.Executable); - ServiceDescriptorAssert.AssertAllOptionalPropertiesAreDefault(desc); + ServiceConfigAssert.AssertAllOptionalPropertiesAreDefault(config); } - private static ServiceDescriptor Load(string exampleName) + private static XmlServiceConfig Load(string exampleName) { string directory = Environment.CurrentDirectory; while (true) @@ -53,7 +53,7 @@ namespace WinSW.Tests.Configuration XmlDocument dom = new XmlDocument(); dom.Load(path); - return new ServiceDescriptor(dom); + return new XmlServiceConfig(dom); } } } diff --git a/src/WinSW.Tests/DownloadConfigTests.cs b/src/WinSW.Tests/DownloadConfigTests.cs index d60b197..d20863c 100644 --- a/src/WinSW.Tests/DownloadConfigTests.cs +++ b/src/WinSW.Tests/DownloadConfigTests.cs @@ -22,10 +22,10 @@ namespace WinSW.Tests { // Roundtrip data Download d = new Download(From, To); - var sd = ConfigXmlBuilder.Create(this.output) + var config = ConfigXmlBuilder.Create(this.output) .WithDownload(d) - .ToServiceDescriptor(true); - var loaded = this.GetSingleEntry(sd); + .ToServiceConfig(true); + var loaded = this.GetSingleEntry(config); // Check default values Assert.False(loaded.FailOnError); @@ -40,10 +40,10 @@ namespace WinSW.Tests { // Roundtrip data Download d = new Download(From, To, true, Download.AuthType.Basic, "aUser", "aPassword", true); - var sd = ConfigXmlBuilder.Create(this.output) + var config = ConfigXmlBuilder.Create(this.output) .WithDownload(d) - .ToServiceDescriptor(true); - var loaded = this.GetSingleEntry(sd); + .ToServiceConfig(true); + var loaded = this.GetSingleEntry(config); // Check default values Assert.True(loaded.FailOnError); @@ -58,10 +58,10 @@ namespace WinSW.Tests { // Roundtrip data Download d = new Download(From, To, false, Download.AuthType.Sspi); - var sd = ConfigXmlBuilder.Create(this.output) + var config = ConfigXmlBuilder.Create(this.output) .WithDownload(d) - .ToServiceDescriptor(true); - var loaded = this.GetSingleEntry(sd); + .ToServiceConfig(true); + var loaded = this.GetSingleEntry(config); // Check default values Assert.False(loaded.FailOnError); @@ -107,11 +107,11 @@ namespace WinSW.Tests { Download d = new Download(From, To, failOnError); - var sd = ConfigXmlBuilder.Create(this.output) + var config = ConfigXmlBuilder.Create(this.output) .WithDownload(d) - .ToServiceDescriptor(true); + .ToServiceConfig(true); - var loaded = this.GetSingleEntry(sd); + var loaded = this.GetSingleEntry(config); Assert.Equal(From, loaded.From); Assert.Equal(To, loaded.To); Assert.Equal(failOnError, loaded.FailOnError); @@ -123,11 +123,11 @@ namespace WinSW.Tests [Fact] public void Download_FailOnError_Undefined() { - var sd = ConfigXmlBuilder.Create(this.output) + var config = ConfigXmlBuilder.Create(this.output) .WithRawEntry("") - .ToServiceDescriptor(true); + .ToServiceConfig(true); - var loaded = this.GetSingleEntry(sd); + var loaded = this.GetSingleEntry(config); Assert.False(loaded.FailOnError); } @@ -138,10 +138,10 @@ namespace WinSW.Tests [InlineData("Sspi")] public void AuthType_Is_CaseInsensitive(string authType) { - var sd = ConfigXmlBuilder.Create(this.output) + var config = ConfigXmlBuilder.Create(this.output) .WithRawEntry("") - .ToServiceDescriptor(true); - var loaded = this.GetSingleEntry(sd); + .ToServiceConfig(true); + var loaded = this.GetSingleEntry(config); Assert.Equal(Download.AuthType.Sspi, loaded.Auth); } @@ -149,11 +149,11 @@ namespace WinSW.Tests public void Should_Fail_On_Unsupported_AuthType() { // TODO: will need refactoring once all fields are being parsed on startup - var sd = ConfigXmlBuilder.Create(this.output) + var config = ConfigXmlBuilder.Create(this.output) .WithRawEntry("") - .ToServiceDescriptor(true); + .ToServiceConfig(true); - var e = Assert.Throws(() => this.GetSingleEntry(sd)); + var e = Assert.Throws(() => this.GetSingleEntry(config)); Assert.StartsWith("Cannot parse Enum value from string 'digest'", e.Message); } @@ -187,19 +187,19 @@ namespace WinSW.Tests } } - private Download GetSingleEntry(ServiceDescriptor sd) + private Download GetSingleEntry(XmlServiceConfig config) { - var downloads = sd.Downloads.ToArray(); + var downloads = config.Downloads.ToArray(); return Assert.Single(downloads); } private void AssertInitializationFails(Download download, string expectedMessagePart = null) { - var sd = ConfigXmlBuilder.Create(this.output) + var config = ConfigXmlBuilder.Create(this.output) .WithDownload(download) - .ToServiceDescriptor(true); + .ToServiceConfig(true); - var e = Assert.Throws(() => this.GetSingleEntry(sd)); + var e = Assert.Throws(() => this.GetSingleEntry(config)); Assert.StartsWith(expectedMessagePart, e.Message); } } diff --git a/src/WinSW.Tests/Extensions/RunawayProcessKillerTest.cs b/src/WinSW.Tests/Extensions/RunawayProcessKillerTest.cs index ee19f06..6316e02 100644 --- a/src/WinSW.Tests/Extensions/RunawayProcessKillerTest.cs +++ b/src/WinSW.Tests/Extensions/RunawayProcessKillerTest.cs @@ -12,7 +12,7 @@ namespace WinSW.Tests.Extensions { public class RunawayProcessKillerExtensionTest : ExtensionTestBase { - private readonly ServiceDescriptor testServiceDescriptor; + private readonly XmlServiceConfig serviceConfig; private readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension)); @@ -37,13 +37,13 @@ $@" "; - this.testServiceDescriptor = ServiceDescriptor.FromXml(seedXml); + this.serviceConfig = XmlServiceConfig.FromXml(seedXml); } [Fact] public void LoadExtensions() { - WinSWExtensionManager manager = new WinSWExtensionManager(this.testServiceDescriptor); + WinSWExtensionManager manager = new WinSWExtensionManager(this.serviceConfig); manager.LoadExtensions(); _ = Assert.Single(manager.Extensions); @@ -57,7 +57,7 @@ $@" [Fact] public void StartStopExtension() { - WinSWExtensionManager manager = new WinSWExtensionManager(this.testServiceDescriptor); + WinSWExtensionManager manager = new WinSWExtensionManager(this.serviceConfig); manager.LoadExtensions(); manager.FireOnWrapperStarted(); manager.FireBeforeWrapperStopped(); @@ -84,10 +84,10 @@ $@" { // Generate extension and ensure that the roundtrip is correct var pidfile = Path.Combine(tmpDir, "process.pid"); - var sd = ConfigXmlBuilder.Create(this.output, id: winswId) + var config = ConfigXmlBuilder.Create(this.output, id: winswId) .WithRunawayProcessKiller(new RunawayProcessKillerExtension(pidfile), extensionId) - .ToServiceDescriptor(); - WinSWExtensionManager manager = new WinSWExtensionManager(sd); + .ToServiceConfig(); + WinSWExtensionManager manager = new WinSWExtensionManager(config); manager.LoadExtensions(); var extension = manager.Extensions[extensionId] as RunawayProcessKillerExtension; Assert.NotNull(extension); diff --git a/src/WinSW.Tests/Extensions/SharedDirectoryMapperConfigTest.cs b/src/WinSW.Tests/Extensions/SharedDirectoryMapperConfigTest.cs index 7a87694..7271aac 100644 --- a/src/WinSW.Tests/Extensions/SharedDirectoryMapperConfigTest.cs +++ b/src/WinSW.Tests/Extensions/SharedDirectoryMapperConfigTest.cs @@ -6,7 +6,7 @@ namespace WinSW.Tests.Extensions { public class SharedDirectoryMapperConfigTest : ExtensionTestBase { - private readonly ServiceDescriptor testServiceDescriptor; + private readonly XmlServiceConfig serviceConfig; private readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(SharedDirectoryMapper)); @@ -35,13 +35,13 @@ $@" "; - this.testServiceDescriptor = ServiceDescriptor.FromXml(seedXml); + this.serviceConfig = XmlServiceConfig.FromXml(seedXml); } [Fact] public void LoadExtensions() { - WinSWExtensionManager manager = new WinSWExtensionManager(this.testServiceDescriptor); + WinSWExtensionManager manager = new WinSWExtensionManager(this.serviceConfig); manager.LoadExtensions(); Assert.Equal(2, manager.Extensions.Count); } @@ -49,7 +49,7 @@ $@" [Fact] public void StartStopExtension() { - WinSWExtensionManager manager = new WinSWExtensionManager(this.testServiceDescriptor); + WinSWExtensionManager manager = new WinSWExtensionManager(this.serviceConfig); manager.LoadExtensions(); manager.FireOnWrapperStarted(); manager.FireBeforeWrapperStopped(); diff --git a/src/WinSW.Tests/ServiceDescriptorTests.cs b/src/WinSW.Tests/ServiceConfigTests.cs similarity index 67% rename from src/WinSW.Tests/ServiceDescriptorTests.cs rename to src/WinSW.Tests/ServiceConfigTests.cs index beaacb7..3f9fd7a 100644 --- a/src/WinSW.Tests/ServiceDescriptorTests.cs +++ b/src/WinSW.Tests/ServiceConfigTests.cs @@ -8,7 +8,7 @@ using Xunit.Abstractions; namespace WinSW.Tests { - public class ServiceDescriptorTests + public class ServiceConfigTests { private const string ExpectedWorkingDirectory = @"Z:\Path\SubPath"; private const string Username = "User"; @@ -18,9 +18,9 @@ namespace WinSW.Tests private readonly ITestOutputHelper output; - private ServiceDescriptor extendedServiceDescriptor; + private XmlServiceConfig extendedServiceConfig; - public ServiceDescriptorTests(ITestOutputHelper output) + public ServiceConfigTests(ITestOutputHelper output) { this.output = output; @@ -40,13 +40,13 @@ $@" {ExpectedWorkingDirectory} C:\logs "; - this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml); + this.extendedServiceConfig = XmlServiceConfig.FromXml(seedXml); } [Fact] public void DefaultStartMode() { - Assert.Equal(ServiceStartMode.Automatic, this.extendedServiceDescriptor.StartMode); + Assert.Equal(ServiceStartMode.Automatic, this.extendedServiceConfig.StartMode); } [Fact] @@ -70,8 +70,8 @@ $@" C:\logs "; - this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml); - _ = Assert.Throws(() => this.extendedServiceDescriptor.StartMode); + this.extendedServiceConfig = XmlServiceConfig.FromXml(seedXml); + _ = Assert.Throws(() => this.extendedServiceConfig.StartMode); } [Fact] @@ -95,48 +95,45 @@ $@" C:\logs "; - this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml); - Assert.Equal(ServiceStartMode.Manual, this.extendedServiceDescriptor.StartMode); + this.extendedServiceConfig = XmlServiceConfig.FromXml(seedXml); + Assert.Equal(ServiceStartMode.Manual, this.extendedServiceConfig.StartMode); } [Fact] public void VerifyWorkingDirectory() { - Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory); - Assert.Equal(ExpectedWorkingDirectory, this.extendedServiceDescriptor.WorkingDirectory); + Assert.Equal(ExpectedWorkingDirectory, this.extendedServiceConfig.WorkingDirectory); } [Fact] public void VerifyServiceLogonRight() { - Assert.True(this.extendedServiceDescriptor.AllowServiceAcountLogonRight); + Assert.True(this.extendedServiceConfig.AllowServiceAcountLogonRight); } [Fact] public void VerifyUsername() { - Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory); - Assert.Equal(Domain + "\\" + Username, this.extendedServiceDescriptor.ServiceAccountUserName); + Assert.Equal(Domain + "\\" + Username, this.extendedServiceConfig.ServiceAccountUserName); } [Fact] public void VerifyPassword() { - Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory); - Assert.Equal(Password, this.extendedServiceDescriptor.ServiceAccountPassword); + Assert.Equal(Password, this.extendedServiceConfig.ServiceAccountPassword); } [Fact] public void Priority() { - var sd = ServiceDescriptor.FromXml("testnormal"); - Assert.Equal(ProcessPriorityClass.Normal, sd.Priority); + var config = XmlServiceConfig.FromXml("testnormal"); + Assert.Equal(ProcessPriorityClass.Normal, config.Priority); - sd = ServiceDescriptor.FromXml("testidle"); - Assert.Equal(ProcessPriorityClass.Idle, sd.Priority); + config = XmlServiceConfig.FromXml("testidle"); + Assert.Equal(ProcessPriorityClass.Idle, config.Priority); - sd = ServiceDescriptor.FromXml("test"); - Assert.Equal(ProcessPriorityClass.Normal, sd.Priority); + config = XmlServiceConfig.FromXml("test"); + Assert.Equal(ProcessPriorityClass.Normal, config.Priority); } [Fact] @@ -145,9 +142,9 @@ $@" const string seedXml = "" + "60sec" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); + var config = XmlServiceConfig.FromXml(seedXml); - Assert.Equal(TimeSpan.FromSeconds(60), serviceDescriptor.StopTimeout); + Assert.Equal(TimeSpan.FromSeconds(60), config.StopTimeout); } [Fact] @@ -156,9 +153,9 @@ $@" const string seedXml = "" + "10min" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); + var config = XmlServiceConfig.FromXml(seedXml); - Assert.Equal(TimeSpan.FromMinutes(10), serviceDescriptor.StopTimeout); + Assert.Equal(TimeSpan.FromMinutes(10), config.StopTimeout); } [Fact] @@ -167,9 +164,9 @@ $@" const string seedXml = "" + "MyTestApp" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); + var config = XmlServiceConfig.FromXml(seedXml); - Assert.Equal("MyTestApp", serviceDescriptor.LogName); + Assert.Equal("MyTestApp", config.LogName); } [Fact] @@ -178,9 +175,9 @@ $@" const string seedXml = "" + "true" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); + var config = XmlServiceConfig.FromXml(seedXml); - Assert.True(serviceDescriptor.OutFileDisabled); + Assert.True(config.OutFileDisabled); } [Fact] @@ -189,9 +186,9 @@ $@" const string seedXml = "" + "true" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); + var config = XmlServiceConfig.FromXml(seedXml); - Assert.True(serviceDescriptor.ErrFileDisabled); + Assert.True(config.ErrFileDisabled); } [Fact] @@ -200,9 +197,9 @@ $@" const string seedXml = "" + ".out.test.log" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); + var config = XmlServiceConfig.FromXml(seedXml); - Assert.Equal(".out.test.log", serviceDescriptor.OutFilePattern); + Assert.Equal(".out.test.log", config.OutFilePattern); } [Fact] @@ -211,9 +208,9 @@ $@" const string seedXml = "" + ".err.test.log" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); + var config = XmlServiceConfig.FromXml(seedXml); - Assert.Equal(".err.test.log", serviceDescriptor.ErrFilePattern); + Assert.Equal(".err.test.log", config.ErrFilePattern); } [Fact] @@ -227,10 +224,10 @@ $@" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); - serviceDescriptor.BaseName = "service"; + var config = XmlServiceConfig.FromXml(seedXml); + config.BaseName = "service"; - var logHandler = serviceDescriptor.LogHandler as SizeBasedRollingLogAppender; + var logHandler = config.LogHandler as SizeBasedRollingLogAppender; Assert.NotNull(logHandler); Assert.Equal(112 * 1024, logHandler.SizeThreshold); Assert.Equal(113, logHandler.FilesToKeep); @@ -247,10 +244,10 @@ $@" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); - serviceDescriptor.BaseName = "service"; + var config = XmlServiceConfig.FromXml(seedXml); + config.BaseName = "service"; - var logHandler = serviceDescriptor.LogHandler as TimeBasedRollingLogAppender; + var logHandler = config.LogHandler as TimeBasedRollingLogAppender; Assert.NotNull(logHandler); Assert.Equal(7, logHandler.Period); Assert.Equal("log pattern", logHandler.Pattern); @@ -268,10 +265,10 @@ $@" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); - serviceDescriptor.BaseName = "service"; + var config = XmlServiceConfig.FromXml(seedXml); + config.BaseName = "service"; - var logHandler = serviceDescriptor.LogHandler as RollingSizeTimeLogAppender; + var logHandler = config.LogHandler as RollingSizeTimeLogAppender; Assert.NotNull(logHandler); Assert.Equal(10240 * 1024, logHandler.SizeThreshold); Assert.Equal("yyyy-MM-dd", logHandler.FilePattern); @@ -289,8 +286,8 @@ $@" + "true1" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); - Assert.False(serviceDescriptor.AllowServiceAcountLogonRight); + var config = XmlServiceConfig.FromXml(seedXml); + Assert.False(config.AllowServiceAcountLogonRight); } [Fact] @@ -303,22 +300,22 @@ $@" + "" + Password + "" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); - Assert.False(serviceDescriptor.AllowServiceAcountLogonRight); + var config = XmlServiceConfig.FromXml(seedXml); + Assert.False(config.AllowServiceAcountLogonRight); } [Fact] public void VerifyResetFailureAfter() { - var sd = ConfigXmlBuilder.Create(this.output).WithTag("resetfailure", "75 sec").ToServiceDescriptor(true); - Assert.Equal(TimeSpan.FromSeconds(75), sd.ResetFailureAfter); + var config = ConfigXmlBuilder.Create(this.output).WithTag("resetfailure", "75 sec").ToServiceConfig(true); + Assert.Equal(TimeSpan.FromSeconds(75), config.ResetFailureAfter); } [Fact] public void VerifyStopTimeout() { - var sd = ConfigXmlBuilder.Create(this.output).WithTag("stoptimeout", "35 secs").ToServiceDescriptor(true); - Assert.Equal(TimeSpan.FromSeconds(35), sd.StopTimeout); + var config = ConfigXmlBuilder.Create(this.output).WithTag("stoptimeout", "35 secs").ToServiceConfig(true); + Assert.Equal(TimeSpan.FromSeconds(35), config.StopTimeout); } /// @@ -327,8 +324,8 @@ $@" [Fact] public void Arguments_LegacyParam() { - var sd = ConfigXmlBuilder.Create(this.output).WithTag("arguments", "arg").ToServiceDescriptor(true); - Assert.Equal("arg", sd.Arguments); + var config = ConfigXmlBuilder.Create(this.output).WithTag("arguments", "arg").ToServiceConfig(true); + Assert.Equal("arg", config.Arguments); } [Theory] @@ -342,8 +339,8 @@ $@" bldr = bldr.WithDelayedAutoStart(); } - var sd = bldr.ToServiceDescriptor(); - Assert.Equal(enabled, sd.DelayedAutoStart); + var config = bldr.ToServiceConfig(); + Assert.Equal(enabled, config.DelayedAutoStart); } [Fact] @@ -378,16 +375,16 @@ $@" "; - ServiceDescriptor descriptor = ServiceDescriptor.FromXml(seedXml); + XmlServiceConfig config = XmlServiceConfig.FromXml(seedXml); - Assert.Equal(prestartExecutable, descriptor.PrestartExecutable); - Assert.Equal(prestartArguments, descriptor.PrestartArguments); - Assert.Equal(poststartExecutable, descriptor.PoststartExecutable); - Assert.Equal(poststartArguments, descriptor.PoststartArguments); - Assert.Equal(prestopExecutable, descriptor.PrestopExecutable); - Assert.Equal(prestopArguments, descriptor.PrestopArguments); - Assert.Equal(poststopExecutable, descriptor.PoststopExecutable); - Assert.Equal(poststopArguments, descriptor.PoststopArguments); + Assert.Equal(prestartExecutable, config.PrestartExecutable); + Assert.Equal(prestartArguments, config.PrestartArguments); + Assert.Equal(poststartExecutable, config.PoststartExecutable); + Assert.Equal(poststartArguments, config.PoststartArguments); + Assert.Equal(prestopExecutable, config.PrestopExecutable); + Assert.Equal(prestopArguments, config.PrestopArguments); + Assert.Equal(poststopExecutable, config.PoststopExecutable); + Assert.Equal(poststopArguments, config.PoststopArguments); } } } diff --git a/src/WinSW.Tests/Util/CommandLineTestHelper.cs b/src/WinSW.Tests/Util/CommandLineTestHelper.cs index 8a91fdd..91feed7 100644 --- a/src/WinSW.Tests/Util/CommandLineTestHelper.cs +++ b/src/WinSW.Tests/Util/CommandLineTestHelper.cs @@ -24,16 +24,16 @@ $@" C:\winsw\logs "; - public static readonly ServiceDescriptor DefaultServiceDescriptor = ServiceDescriptor.FromXml(SeedXml); + public static readonly XmlServiceConfig DefaultServiceConfig = XmlServiceConfig.FromXml(SeedXml); /// /// Runs a simle test, which returns the output CLI /// /// CLI arguments to be passed - /// Optional Service descriptor (will be used for initializationpurposes) + /// Optional Service config (will be used for initialization purposes) /// STDOUT if there's no exceptions /// Command failure - public static string Test(string[] arguments, ServiceDescriptor descriptor = null) + public static string Test(string[] arguments, XmlServiceConfig config = null) { TextWriter tmpOut = Console.Out; TextWriter tmpError = Console.Error; @@ -43,7 +43,7 @@ $@" Console.SetOut(swOut); Console.SetError(swError); - ServiceDescriptor.TestDescriptor = descriptor ?? DefaultServiceDescriptor; + XmlServiceConfig.TestConfig = config ?? DefaultServiceConfig; try { _ = Program.Run(arguments); @@ -52,7 +52,7 @@ $@" { Console.SetOut(tmpOut); Console.SetError(tmpError); - ServiceDescriptor.TestDescriptor = null; + XmlServiceConfig.TestConfig = null; } Assert.Equal(string.Empty, swError.ToString()); @@ -63,9 +63,9 @@ $@" /// Runs a simle test, which returns the output CLI /// /// CLI arguments to be passed - /// Optional Service descriptor (will be used for initializationpurposes) + /// Optional Service config (will be used for initialization purposes) /// Test results - public static CommandLineTestResult ErrorTest(string[] arguments, ServiceDescriptor descriptor = null) + public static CommandLineTestResult ErrorTest(string[] arguments, XmlServiceConfig config = null) { Exception exception = null; @@ -77,7 +77,7 @@ $@" Console.SetOut(swOut); Console.SetError(swError); - ServiceDescriptor.TestDescriptor = descriptor ?? DefaultServiceDescriptor; + XmlServiceConfig.TestConfig = config ?? DefaultServiceConfig; Program.TestExceptionHandler = (e, _) => exception = e; try { @@ -91,7 +91,7 @@ $@" { Console.SetOut(tmpOut); Console.SetError(tmpError); - ServiceDescriptor.TestDescriptor = null; + XmlServiceConfig.TestConfig = null; Program.TestExceptionHandler = null; } diff --git a/src/WinSW.Tests/Util/ConfigXmlBuilder.cs b/src/WinSW.Tests/Util/ConfigXmlBuilder.cs index 48e4789..202758c 100644 --- a/src/WinSW.Tests/Util/ConfigXmlBuilder.cs +++ b/src/WinSW.Tests/Util/ConfigXmlBuilder.cs @@ -104,9 +104,9 @@ namespace WinSW.Tests.Util return res; } - public ServiceDescriptor ToServiceDescriptor(bool dumpConfig = false) + public XmlServiceConfig ToServiceConfig(bool dumpConfig = false) { - return ServiceDescriptor.FromXml(this.ToXmlString(dumpConfig)); + return XmlServiceConfig.FromXml(this.ToXmlString(dumpConfig)); } public ConfigXmlBuilder WithRawEntry(string entry) diff --git a/src/WinSW.Tests/Util/ServiceConfigAssert.cs b/src/WinSW.Tests/Util/ServiceConfigAssert.cs new file mode 100644 index 0000000..dec9553 --- /dev/null +++ b/src/WinSW.Tests/Util/ServiceConfigAssert.cs @@ -0,0 +1,34 @@ +using System.Reflection; +using WinSW.Configuration; +using Xunit; + +namespace WinSW.Tests.Util +{ + public static class ServiceConfigAssert + { + public static void AssertAllOptionalPropertiesAreDefault(XmlServiceConfig config) + { + var testConfig = new TestServiceConfig(config); + foreach (var property in typeof(ServiceConfig).GetProperties()) + { + if (property.GetMethod!.IsVirtual) + { + Assert.Equal(property.GetValue(testConfig, null), property.GetValue(config, null)); + } + } + } + + private sealed class TestServiceConfig : ServiceConfig + { + private readonly XmlServiceConfig config; + + internal TestServiceConfig(XmlServiceConfig config) => this.config = config; + + public override string FullPath => this.config.FullPath; + + public override string Id => this.config.Id; + + public override string Executable => this.config.Executable; + } + } +} diff --git a/src/WinSW.Tests/Util/ServiceDescriptorAssert.cs b/src/WinSW.Tests/Util/ServiceDescriptorAssert.cs deleted file mode 100644 index b996074..0000000 --- a/src/WinSW.Tests/Util/ServiceDescriptorAssert.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Collections.Generic; -using System.Reflection; -using WinSW.Configuration; -using Xunit; - -namespace WinSW.Tests.Util -{ - public static class ServiceDescriptorAssert - { - // TODO: convert to Extension attributes once the .NET dependency is upgraded - // BTW there is a way to get them working in .NET2, but KISS - public static void AssertPropertyIsDefault(ServiceDescriptor desc, string property) - { - PropertyInfo actualProperty = typeof(ServiceDescriptor).GetProperty(property); - Assert.NotNull(actualProperty); - - PropertyInfo defaultProperty = typeof(DefaultWinSWSettings).GetProperty(property); - Assert.NotNull(defaultProperty); - - Assert.Equal(defaultProperty.GetValue(ServiceDescriptor.Defaults, null), actualProperty.GetValue(desc, null)); - } - - public static void AssertPropertyIsDefault(ServiceDescriptor desc, List properties) - { - foreach (var prop in properties) - { - AssertPropertyIsDefault(desc, prop); - } - } - - public static void AssertAllOptionalPropertiesAreDefault(ServiceDescriptor desc) - { - AssertPropertyIsDefault(desc, AllOptionalProperties); - } - - private static List AllProperties - { - get - { - var res = new List(); - var properties = typeof(IWinSWConfiguration).GetProperties(); - foreach (var prop in properties) - { - res.Add(prop.Name); - } - - return res; - } - } - - private static List AllOptionalProperties - { - get - { - var properties = AllProperties; - properties.Remove("FullPath"); - properties.Remove("Id"); - properties.Remove("Executable"); - properties.Remove("WorkingDirectory"); - return properties; - } - } - } -} diff --git a/src/WinSW/Program.cs b/src/WinSW/Program.cs index f7bb5e2..d988e13 100644 --- a/src/WinSW/Program.cs +++ b/src/WinSW/Program.cs @@ -71,20 +71,20 @@ namespace WinSW { Handler = CommandHandler.Create((string? pathToConfig) => { - ServiceDescriptor descriptor; + XmlServiceConfig config; try { - descriptor = ServiceDescriptor.Create(pathToConfig); + config = XmlServiceConfig.Create(pathToConfig); } catch (FileNotFoundException) { throw new CommandException("The specified command or file was not found."); } - InitLoggers(descriptor, enableConsoleLogging: false); + InitLoggers(config, enableConsoleLogging: false); Log.Debug("Starting WinSW in service mode"); - ServiceBase.Run(new WrapperService(descriptor)); + ServiceBase.Run(new WrapperService(config)); }), }; @@ -320,8 +320,8 @@ namespace WinSW void Install(string? pathToConfig, bool noElevate, string? username, string? password) { - ServiceDescriptor descriptor = ServiceDescriptor.Create(pathToConfig); - InitLoggers(descriptor, enableConsoleLogging: true); + XmlServiceConfig config = XmlServiceConfig.Create(pathToConfig); + InitLoggers(config, enableConsoleLogging: true); if (!elevated) { @@ -329,25 +329,25 @@ namespace WinSW return; } - Log.Info("Installing the service with id '" + descriptor.Id + "'"); + Log.Info("Installing the service with id '" + config.Id + "'"); using ServiceManager scm = ServiceManager.Open(); - if (scm.ServiceExists(descriptor.Id)) + if (scm.ServiceExists(config.Id)) { - Console.WriteLine("Service with id '" + descriptor.Id + "' already exists"); + Console.WriteLine("Service with id '" + config.Id + "' already exists"); Console.WriteLine("To install the service, delete the existing one or change service Id in the configuration file"); - throw new CommandException("Installation failure: Service with id '" + descriptor.Id + "' already exists"); + throw new CommandException("Installation failure: Service with id '" + config.Id + "' already exists"); } - if (descriptor.HasServiceAccount()) + if (config.HasServiceAccount()) { - username = descriptor.ServiceAccountUserName ?? username; - password = descriptor.ServiceAccountPassword ?? password; + username = config.ServiceAccountUserName ?? username; + password = config.ServiceAccountPassword ?? password; if (username is null || password is null) { - switch (descriptor.ServiceAccountPrompt) + switch (config.ServiceAccountPrompt) { case "dialog": Credentials.PropmtForCredentialsDialog( @@ -370,45 +370,45 @@ namespace WinSW } using Service sc = scm.CreateService( - descriptor.Id, - descriptor.Caption, - descriptor.StartMode, - "\"" + descriptor.ExecutablePath + "\"" + (pathToConfig != null ? " \"" + Path.GetFullPath(pathToConfig) + "\"" : null), - descriptor.ServiceDependencies, + config.Id, + config.Caption, + config.StartMode, + "\"" + config.ExecutablePath + "\"" + (pathToConfig != null ? " \"" + Path.GetFullPath(pathToConfig) + "\"" : null), + config.ServiceDependencies, username, password); - string description = descriptor.Description; + string description = config.Description; if (description.Length != 0) { sc.SetDescription(description); } - SC_ACTION[] actions = descriptor.FailureActions; + SC_ACTION[] actions = config.FailureActions; if (actions.Length > 0) { - sc.SetFailureActions(descriptor.ResetFailureAfter, actions); + sc.SetFailureActions(config.ResetFailureAfter, actions); } - bool isDelayedAutoStart = descriptor.StartMode == ServiceStartMode.Automatic && descriptor.DelayedAutoStart; + bool isDelayedAutoStart = config.StartMode == ServiceStartMode.Automatic && config.DelayedAutoStart; if (isDelayedAutoStart) { sc.SetDelayedAutoStart(true); } - if (descriptor.PreshutdownTimeout is TimeSpan preshutdownTimeout) + if (config.PreshutdownTimeout is TimeSpan preshutdownTimeout) { sc.SetPreshutdownTimeout(preshutdownTimeout); } - string? securityDescriptor = descriptor.SecurityDescriptor; + string? securityDescriptor = config.SecurityDescriptor; if (securityDescriptor != null) { // throws ArgumentException sc.SetSecurityDescriptor(new RawSecurityDescriptor(securityDescriptor)); } - string eventLogSource = descriptor.Id; + string eventLogSource = config.Id; if (!EventLog.SourceExists(eventLogSource)) { EventLog.CreateEventSource(eventLogSource, "Application"); @@ -434,8 +434,8 @@ namespace WinSW void Uninstall(string? pathToConfig, bool noElevate) { - ServiceDescriptor descriptor = ServiceDescriptor.Create(pathToConfig); - InitLoggers(descriptor, enableConsoleLogging: true); + XmlServiceConfig config = XmlServiceConfig.Create(pathToConfig); + InitLoggers(config, enableConsoleLogging: true); if (!elevated) { @@ -443,18 +443,18 @@ namespace WinSW return; } - Log.Info("Uninstalling the service with id '" + descriptor.Id + "'"); + Log.Info("Uninstalling the service with id '" + config.Id + "'"); using ServiceManager scm = ServiceManager.Open(); try { - using Service sc = scm.OpenService(descriptor.Id); + using Service sc = scm.OpenService(config.Id); if (sc.Status == ServiceControllerStatus.Running) { // We could fail the opeartion here, but it would be an incompatible change. // So it is just a warning - Log.Warn("The service with id '" + descriptor.Id + "' is running. It may be impossible to uninstall it"); + Log.Warn("The service with id '" + config.Id + "' is running. It may be impossible to uninstall it"); } sc.Delete(); @@ -464,18 +464,18 @@ namespace WinSW switch (inner.NativeErrorCode) { case Errors.ERROR_SERVICE_DOES_NOT_EXIST: - Log.Warn("The service with id '" + descriptor.Id + "' does not exist. Nothing to uninstall"); + Log.Warn("The service with id '" + config.Id + "' does not exist. Nothing to uninstall"); break; // there's no such service, so consider it already uninstalled case Errors.ERROR_SERVICE_MARKED_FOR_DELETE: - Log.Error("Failed to uninstall the service with id '" + descriptor.Id + "'" + Log.Error("Failed to uninstall the service with id '" + config.Id + "'" + ". It has been marked for deletion."); // TODO: change the default behavior to Error? break; // it's already uninstalled, so consider it a success default: - Log.Fatal("Failed to uninstall the service with id '" + descriptor.Id + "'. Error code is '" + inner.NativeErrorCode + "'"); + Log.Fatal("Failed to uninstall the service with id '" + config.Id + "'. Error code is '" + inner.NativeErrorCode + "'"); throw; } } @@ -483,8 +483,8 @@ namespace WinSW void Start(string? pathToConfig, bool noElevate) { - ServiceDescriptor descriptor = ServiceDescriptor.Create(pathToConfig); - InitLoggers(descriptor, enableConsoleLogging: true); + XmlServiceConfig config = XmlServiceConfig.Create(pathToConfig); + InitLoggers(config, enableConsoleLogging: true); if (!elevated) { @@ -492,9 +492,9 @@ namespace WinSW return; } - Log.Info("Starting the service with id '" + descriptor.Id + "'"); + Log.Info("Starting the service with id '" + config.Id + "'"); - using var svc = new ServiceController(descriptor.Id); + using var svc = new ServiceController(config.Id); try { @@ -508,14 +508,14 @@ namespace WinSW catch (InvalidOperationException e) when (e.InnerException is Win32Exception inner && inner.NativeErrorCode == Errors.ERROR_SERVICE_ALREADY_RUNNING) { - Log.Info($"The service with ID '{descriptor.Id}' has already been started"); + Log.Info($"The service with ID '{config.Id}' has already been started"); } } void Stop(string? pathToConfig, bool noElevate, bool noWait, bool force) { - ServiceDescriptor descriptor = ServiceDescriptor.Create(pathToConfig); - InitLoggers(descriptor, enableConsoleLogging: true); + XmlServiceConfig config = XmlServiceConfig.Create(pathToConfig); + InitLoggers(config, enableConsoleLogging: true); if (!elevated) { @@ -523,9 +523,9 @@ namespace WinSW return; } - Log.Info("Stopping the service with id '" + descriptor.Id + "'"); + Log.Info("Stopping the service with id '" + config.Id + "'"); - using var svc = new ServiceController(descriptor.Id); + using var svc = new ServiceController(config.Id); try { @@ -567,8 +567,8 @@ namespace WinSW void Restart(string? pathToConfig, bool noElevate, bool force) { - ServiceDescriptor descriptor = ServiceDescriptor.Create(pathToConfig); - InitLoggers(descriptor, enableConsoleLogging: true); + XmlServiceConfig config = XmlServiceConfig.Create(pathToConfig); + InitLoggers(config, enableConsoleLogging: true); if (!elevated) { @@ -576,9 +576,9 @@ namespace WinSW return; } - Log.Info("Restarting the service with id '" + descriptor.Id + "'"); + Log.Info("Restarting the service with id '" + config.Id + "'"); - using var svc = new ServiceController(descriptor.Id); + using var svc = new ServiceController(config.Id); List? startedDependentServices = null; @@ -632,19 +632,19 @@ namespace WinSW void RestartSelf(string? pathToConfig) { - ServiceDescriptor descriptor = ServiceDescriptor.Create(pathToConfig); - InitLoggers(descriptor, enableConsoleLogging: true); + XmlServiceConfig config = XmlServiceConfig.Create(pathToConfig); + InitLoggers(config, enableConsoleLogging: true); if (!elevated) { throw new CommandException(new Win32Exception(Errors.ERROR_ACCESS_DENIED)); } - Log.Info("Restarting the service with id '" + descriptor.Id + "'"); + Log.Info("Restarting the service with id '" + config.Id + "'"); // run restart from another process group. see README.md for why this is useful. - if (!ProcessApis.CreateProcess(null, descriptor.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, ProcessApis.CREATE_NEW_PROCESS_GROUP, IntPtr.Zero, null, default, out _)) + if (!ProcessApis.CreateProcess(null, config.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, ProcessApis.CREATE_NEW_PROCESS_GROUP, IntPtr.Zero, null, default, out _)) { throw new CommandException("Failed to invoke restart: " + Marshal.GetLastWin32Error()); } @@ -652,11 +652,11 @@ namespace WinSW static void Status(string? pathToConfig) { - ServiceDescriptor descriptor = ServiceDescriptor.Create(pathToConfig); - InitLoggers(descriptor, enableConsoleLogging: true); + XmlServiceConfig config = XmlServiceConfig.Create(pathToConfig); + InitLoggers(config, enableConsoleLogging: true); - Log.Debug("User requested the status of the process with id '" + descriptor.Id + "'"); - using var svc = new ServiceController(descriptor.Id); + Log.Debug("User requested the status of the process with id '" + config.Id + "'"); + using var svc = new ServiceController(config.Id); try { Console.WriteLine(svc.Status == ServiceControllerStatus.Running ? "Started" : "Stopped"); @@ -670,8 +670,8 @@ namespace WinSW void Test(string? pathToConfig, bool noElevate, int? timeout, bool noBreak) { - ServiceDescriptor descriptor = ServiceDescriptor.Create(pathToConfig); - InitLoggers(descriptor, enableConsoleLogging: true); + XmlServiceConfig config = XmlServiceConfig.Create(pathToConfig); + InitLoggers(config, enableConsoleLogging: true); if (!elevated) { @@ -679,7 +679,7 @@ namespace WinSW return; } - using WrapperService wsvc = new WrapperService(descriptor); + using WrapperService wsvc = new WrapperService(config); wsvc.RaiseOnStart(args); try { @@ -715,8 +715,8 @@ namespace WinSW void Refresh(string? pathToConfig, bool noElevate) { - ServiceDescriptor descriptor = ServiceDescriptor.Create(pathToConfig); - InitLoggers(descriptor, enableConsoleLogging: true); + XmlServiceConfig config = XmlServiceConfig.Create(pathToConfig); + InitLoggers(config, enableConsoleLogging: true); if (!elevated) { @@ -727,30 +727,30 @@ namespace WinSW using ServiceManager scm = ServiceManager.Open(); try { - using Service sc = scm.OpenService(descriptor.Id); + using Service sc = scm.OpenService(config.Id); - sc.ChangeConfig(descriptor.Caption, descriptor.StartMode, descriptor.ServiceDependencies); + sc.ChangeConfig(config.Caption, config.StartMode, config.ServiceDependencies); - sc.SetDescription(descriptor.Description); + sc.SetDescription(config.Description); - SC_ACTION[] actions = descriptor.FailureActions; + SC_ACTION[] actions = config.FailureActions; if (actions.Length > 0) { - sc.SetFailureActions(descriptor.ResetFailureAfter, actions); + sc.SetFailureActions(config.ResetFailureAfter, actions); } - bool isDelayedAutoStart = descriptor.StartMode == ServiceStartMode.Automatic && descriptor.DelayedAutoStart; + bool isDelayedAutoStart = config.StartMode == ServiceStartMode.Automatic && config.DelayedAutoStart; if (isDelayedAutoStart) { sc.SetDelayedAutoStart(true); } - if (descriptor.PreshutdownTimeout is TimeSpan preshutdownTimeout) + if (config.PreshutdownTimeout is TimeSpan preshutdownTimeout) { sc.SetPreshutdownTimeout(preshutdownTimeout); } - string? securityDescriptor = descriptor.SecurityDescriptor; + string? securityDescriptor = config.SecurityDescriptor; if (securityDescriptor != null) { // throws ArgumentException @@ -807,9 +807,9 @@ namespace WinSW [MethodImpl(MethodImplOptions.NoInlining)] private static void ThrowNoSuchService(Win32Exception inner) => throw new CommandException(inner); - private static void InitLoggers(ServiceDescriptor descriptor, bool enableConsoleLogging) + private static void InitLoggers(XmlServiceConfig config, bool enableConsoleLogging) { - if (ServiceDescriptor.TestDescriptor != null) + if (XmlServiceConfig.TestConfig != null) { return; } @@ -828,7 +828,7 @@ namespace WinSW List appenders = new List(); // .wrapper.log - string wrapperLogPath = Path.Combine(descriptor.LogDirectory, descriptor.BaseName + ".wrapper.log"); + string wrapperLogPath = Path.Combine(config.LogDirectory, config.BaseName + ".wrapper.log"); var wrapperLog = new FileAppender { AppendToFile = true, diff --git a/src/WinSW/WrapperService.cs b/src/WinSW/WrapperService.cs index be11800..8594736 100644 --- a/src/WinSW/WrapperService.cs +++ b/src/WinSW/WrapperService.cs @@ -17,7 +17,7 @@ namespace WinSW public sealed class WrapperService : ServiceBase, IEventLogger, IServiceEventLog { private readonly Process process = new Process(); - private readonly ServiceDescriptor descriptor; + private readonly XmlServiceConfig config; private Dictionary? envs; internal WinSWExtensionManager ExtensionManager { get; } @@ -45,11 +45,11 @@ namespace WinSW /// public static Version Version => Assembly.GetExecutingAssembly().GetName().Version!; - public WrapperService(ServiceDescriptor descriptor) + public WrapperService(XmlServiceConfig config) { - this.descriptor = descriptor; - this.ServiceName = this.descriptor.Id; - this.ExtensionManager = new WinSWExtensionManager(this.descriptor); + this.config = config; + this.ServiceName = config.Id; + this.ExtensionManager = new WinSWExtensionManager(config); this.CanShutdown = true; this.CanStop = true; this.CanPauseAndContinue = false; @@ -59,12 +59,12 @@ namespace WinSW // Register the event log provider eventLogProvider.Service = this; - if (descriptor.Preshutdown) + if (config.Preshutdown) { this.AcceptPreshutdown(); } - Environment.CurrentDirectory = descriptor.WorkingDirectory; + Environment.CurrentDirectory = config.WorkingDirectory; } /// @@ -73,7 +73,7 @@ namespace WinSW /// private void HandleFileCopies() { - var file = this.descriptor.BasePath + ".copies"; + var file = this.config.BasePath + ".copies"; if (!File.Exists(file)) { return; // nothing to handle @@ -123,14 +123,14 @@ namespace WinSW /// Log Handler, which should be used for the spawned process private LogHandler CreateExecutableLogHandler() { - string logDirectory = this.descriptor.LogDirectory; + string logDirectory = this.config.LogDirectory; if (!Directory.Exists(logDirectory)) { Directory.CreateDirectory(logDirectory); } - LogHandler logAppender = this.descriptor.LogHandler; + LogHandler logAppender = this.config.LogHandler; logAppender.EventLogger = this; return logAppender; } @@ -243,12 +243,12 @@ namespace WinSW private void DoStart() { - this.envs = this.descriptor.EnvironmentVariables; + this.envs = this.config.EnvironmentVariables; this.HandleFileCopies(); // handle downloads - List downloads = this.descriptor.Downloads; + List downloads = this.config.Downloads; Task[] tasks = new Task[downloads.Count]; for (int i = 0; i < downloads.Count; i++) { @@ -287,10 +287,10 @@ namespace WinSW try { - string? prestartExecutable = this.descriptor.PrestartExecutable; + string? prestartExecutable = this.config.PrestartExecutable; if (prestartExecutable != null) { - using Process process = this.StartProcess(prestartExecutable, this.descriptor.PrestartArguments); + using Process process = this.StartProcess(prestartExecutable, this.config.PrestartArguments); this.WaitForProcessToExit(process); this.LogInfo($"Pre-start process '{process.Format()}' exited with code {process.ExitCode}."); } @@ -300,24 +300,24 @@ namespace WinSW Log.Error(e); } - string startArguments = this.descriptor.StartArguments ?? this.descriptor.Arguments; + string startArguments = this.config.StartArguments ?? this.config.Arguments; - this.LogInfo("Starting " + this.descriptor.Executable); + this.LogInfo("Starting " + this.config.Executable); // Load and start extensions this.ExtensionManager.LoadExtensions(); this.ExtensionManager.FireOnWrapperStarted(); LogHandler executableLogHandler = this.CreateExecutableLogHandler(); - this.StartProcess(this.process, startArguments, this.descriptor.Executable, executableLogHandler); + this.StartProcess(this.process, startArguments, this.config.Executable, executableLogHandler); this.ExtensionManager.FireOnProcessStarted(this.process); try { - string? poststartExecutable = this.descriptor.PoststartExecutable; + string? poststartExecutable = this.config.PoststartExecutable; if (poststartExecutable != null) { - using Process process = this.StartProcess(poststartExecutable, this.descriptor.PoststartArguments, process => + using Process process = this.StartProcess(poststartExecutable, this.config.PoststartArguments, process => { this.LogInfo($"Post-start process '{process.Format()}' exited with code {process.ExitCode}."); }); @@ -336,10 +336,10 @@ namespace WinSW { try { - string? prestopExecutable = this.descriptor.PrestopExecutable; + string? prestopExecutable = this.config.PrestopExecutable; if (prestopExecutable != null) { - using Process process = this.StartProcess(prestopExecutable, this.descriptor.PrestopArguments); + using Process process = this.StartProcess(prestopExecutable, this.config.PrestopArguments); this.WaitForProcessToExit(process); this.LogInfo($"Pre-stop process '{process.Format()}' exited with code {process.ExitCode}."); } @@ -349,15 +349,15 @@ namespace WinSW Log.Error(e); } - string? stopArguments = this.descriptor.StopArguments; - this.LogInfo("Stopping " + this.descriptor.Id); + string? stopArguments = this.config.StopArguments; + this.LogInfo("Stopping " + this.config.Id); this.orderlyShutdown = true; this.process.EnableRaisingEvents = false; if (stopArguments is null) { Log.Debug("ProcessKill " + this.process.Id); - ProcessHelper.StopProcessTree(this.process, this.descriptor.StopTimeout); + ProcessHelper.StopProcessTree(this.process, this.config.StopTimeout); this.ExtensionManager.FireOnProcessTerminated(this.process); } else @@ -366,7 +366,7 @@ namespace WinSW Process stopProcess = new Process(); - string stopExecutable = this.descriptor.StopExecutable ?? this.descriptor.Executable; + string stopExecutable = this.config.StopExecutable ?? this.config.Executable; // TODO: Redirect logging to Log4Net once https://github.com/kohsuke/winsw/pull/213 is integrated this.StartProcess(stopProcess, stopArguments, stopExecutable, null); @@ -378,10 +378,10 @@ namespace WinSW try { - string? poststopExecutable = this.descriptor.PoststopExecutable; + string? poststopExecutable = this.config.PoststopExecutable; if (poststopExecutable != null) { - using Process process = this.StartProcess(poststopExecutable, this.descriptor.PoststopArguments); + using Process process = this.StartProcess(poststopExecutable, this.config.PoststopArguments); this.WaitForProcessToExit(process); this.LogInfo($"Post-stop process '{process.Format()}' exited with code {process.ExitCode}."); } @@ -394,12 +394,12 @@ namespace WinSW // Stop extensions this.ExtensionManager.FireBeforeWrapperStopped(); - if (this.shuttingdown && this.descriptor.BeepOnShutdown) + if (this.shuttingdown && this.config.BeepOnShutdown) { Console.Beep(); } - Log.Info("Finished " + this.descriptor.Id); + Log.Info("Finished " + this.config.Id); } private void WaitForProcessToExit(Process process) @@ -485,11 +485,11 @@ namespace WinSW executable: executable, arguments: arguments, envVars: this.envs, - workingDirectory: this.descriptor.WorkingDirectory, - priority: this.descriptor.Priority, + workingDirectory: this.config.WorkingDirectory, + priority: this.config.Priority, onExited: OnProcessCompleted, logHandler: logHandler, - hideWindow: this.descriptor.HideWindow); + hideWindow: this.config.HideWindow); } private Process StartProcess(string executable, string? arguments, Action? onExited = null) @@ -497,7 +497,7 @@ namespace WinSW var info = new ProcessStartInfo(executable, arguments) { UseShellExecute = false, - WorkingDirectory = this.descriptor.WorkingDirectory, + WorkingDirectory = this.config.WorkingDirectory, }; Process process = Process.Start(info);