diff --git a/Directory.Build.props b/Directory.Build.props index b3cf3c1..402beb4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,13 @@  + true full $(MSBuildThisFileDirectory)artifacts\ + + + + diff --git a/src/.editorconfig b/src/.editorconfig new file mode 100644 index 0000000..ddf3e93 --- /dev/null +++ b/src/.editorconfig @@ -0,0 +1,70 @@ +[*.cs] + +# SA0001: XML comment analysis is disabled due to project configuration +dotnet_diagnostic.SA0001.severity = none + +# SA1114: Parameter list should follow declaration +dotnet_diagnostic.SA1114.severity = none + +# SA1124: Do not use regions +dotnet_diagnostic.SA1124.severity = none + +# SA1201: Elements should appear in the correct order +dotnet_diagnostic.SA1201.severity = none + +# SA1202: Elements should be ordered by access +dotnet_diagnostic.SA1202.severity = none + +# SA1401: Fields should be private +dotnet_diagnostic.SA1401.severity = none + +# SA1402: File may only contain a single type +dotnet_diagnostic.SA1402.severity = none + +# SA1405: Debug.Assert should provide message text +dotnet_diagnostic.SA1405.severity = none + +# SA1413: Use trailing comma in multi-line initializers +dotnet_diagnostic.SA1413.severity = none + +# SA1600: Elements should be documented +dotnet_diagnostic.SA1600.severity = none + +# SA1601: Partial elements should be documented +dotnet_diagnostic.SA1601.severity = none + +# SA1602: Enumeration items should be documented +dotnet_diagnostic.SA1602.severity = none + +# SA1604: Element documentation should have summary +dotnet_diagnostic.SA1604.severity = none + +# SA1606: Element documentation should have summary text +dotnet_diagnostic.SA1606.severity = none + +# SA1611: Element parameters should be documented +dotnet_diagnostic.SA1611.severity = none + +# SA1615: Element return value should be documented +dotnet_diagnostic.SA1615.severity = none + +# SA1618: Generic type parameters should be documented +dotnet_diagnostic.SA1618.severity = none + +# SA1623: Property summary documentation should match accessors +dotnet_diagnostic.SA1623.severity = none + +# SA1627: Documentation text should not be empty +dotnet_diagnostic.SA1627.severity = none + +# SA1629: Documentation text should end with a period +dotnet_diagnostic.SA1629.severity = none + +# SA1633: File should have header +dotnet_diagnostic.SA1633.severity = none + +# SA1642: Constructor summary documentation should begin with standard text +dotnet_diagnostic.SA1642.severity = none + +# SA1649: File name should match first type name +dotnet_diagnostic.SA1649.severity = none diff --git a/src/Core/ServiceWrapper/Logging/WrapperServiceEventLogProvider.cs b/src/Core/ServiceWrapper/Logging/WrapperServiceEventLogProvider.cs index be7cad5..462b419 100644 --- a/src/Core/ServiceWrapper/Logging/WrapperServiceEventLogProvider.cs +++ b/src/Core/ServiceWrapper/Logging/WrapperServiceEventLogProvider.cs @@ -1,20 +1,20 @@ using System.Diagnostics; -namespace winsw.Logging +namespace WinSW.Logging { /// /// Implements caching of the WindowsService reference in WinSW. /// public class WrapperServiceEventLogProvider : IServiceEventLogProvider { - public WrapperService? service { get; set; } + public WrapperService? Service { get; set; } - public EventLog? locate() + public EventLog? Locate() { - WrapperService? _service = service; - if (_service != null && !_service.IsShuttingDown) + WrapperService? service = this.Service; + if (service != null && !service.IsShuttingDown) { - return _service.EventLog; + return service.EventLog; } // By default return null diff --git a/src/Core/ServiceWrapper/Program.cs b/src/Core/ServiceWrapper/Program.cs index 7505561..2d70599 100644 --- a/src/Core/ServiceWrapper/Program.cs +++ b/src/Core/ServiceWrapper/Program.cs @@ -16,10 +16,10 @@ using log4net.Appender; using log4net.Config; using log4net.Core; using log4net.Layout; -using winsw.Logging; -using winsw.Native; +using WinSW.Logging; +using WinSW.Native; -namespace winsw +namespace WinSW { public static class Program { @@ -456,7 +456,6 @@ namespace winsw default: throw; - } } } @@ -530,7 +529,6 @@ namespace winsw default: throw; - } } @@ -723,7 +721,7 @@ namespace winsw { Name = "Wrapper event log", Threshold = eventLogLevel, - provider = WrapperService.eventLogProvider, + Provider = WrapperService.eventLogProvider, }; systemEventLogger.ActivateOptions(); appenders.Add(systemEventLogger); diff --git a/src/Core/ServiceWrapper/ServiceControllerExtension.cs b/src/Core/ServiceWrapper/ServiceControllerExtension.cs index 17c0326..e5af01d 100644 --- a/src/Core/ServiceWrapper/ServiceControllerExtension.cs +++ b/src/Core/ServiceWrapper/ServiceControllerExtension.cs @@ -2,7 +2,7 @@ using System.ServiceProcess; using TimeoutException = System.ServiceProcess.TimeoutException; -namespace winsw +namespace WinSW { internal static class ServiceControllerExtension { diff --git a/src/Core/ServiceWrapper/UserException.cs b/src/Core/ServiceWrapper/UserException.cs index 3234730..0a732f0 100644 --- a/src/Core/ServiceWrapper/UserException.cs +++ b/src/Core/ServiceWrapper/UserException.cs @@ -1,6 +1,6 @@ using System; -namespace winsw +namespace WinSW { internal sealed class UserException : Exception { diff --git a/src/Core/ServiceWrapper/WrapperService.cs b/src/Core/ServiceWrapper/WrapperService.cs index 5e478ec..0861982 100644 --- a/src/Core/ServiceWrapper/WrapperService.cs +++ b/src/Core/ServiceWrapper/WrapperService.cs @@ -8,36 +8,37 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using log4net; -using winsw.Extensions; -using winsw.Logging; -using winsw.Native; -using winsw.Util; +using WinSW.Extensions; +using WinSW.Logging; +using WinSW.Native; +using WinSW.Util; -namespace winsw +namespace WinSW { - public class WrapperService : ServiceBase, EventLogger + public class WrapperService : ServiceBase, IEventLogger { - private ServiceApis.SERVICE_STATUS _wrapperServiceStatus; + private ServiceApis.SERVICE_STATUS wrapperServiceStatus; - private readonly Process _process = new Process(); - private readonly ServiceDescriptor _descriptor; - private Dictionary? _envs; + private readonly Process process = new Process(); + private readonly ServiceDescriptor descriptor; + private Dictionary? envs; - internal WinSWExtensionManager ExtensionManager { get; private set; } + internal WinSWExtensionManager ExtensionManager { get; } private static readonly ILog Log = LogManager.GetLogger( #if NETCOREAPP Assembly.GetExecutingAssembly(), #endif "WinSW"); + internal static readonly WrapperServiceEventLogProvider eventLogProvider = new WrapperServiceEventLogProvider(); /// /// Indicates to the watch dog thread that we are going to terminate the process, /// so don't try to kill us when the child exits. /// - private bool _orderlyShutdown; - private bool _systemShuttingdown; + private bool orderlyShutdown; + private bool systemShuttingdown; /// /// Version of Windows service wrapper @@ -50,24 +51,25 @@ namespace winsw /// /// Indicates that the system is shutting down. /// - public bool IsShuttingDown => _systemShuttingdown; + public bool IsShuttingDown => this.systemShuttingdown; public WrapperService(ServiceDescriptor descriptor) { - _descriptor = descriptor; - ServiceName = _descriptor.Id; - ExtensionManager = new WinSWExtensionManager(_descriptor); - CanShutdown = true; - CanStop = true; - CanPauseAndContinue = false; - AutoLog = true; - _systemShuttingdown = false; + this.descriptor = descriptor; + this.ServiceName = this.descriptor.Id; + this.ExtensionManager = new WinSWExtensionManager(this.descriptor); + this.CanShutdown = true; + this.CanStop = true; + this.CanPauseAndContinue = false; + this.AutoLog = true; + this.systemShuttingdown = false; // Register the event log provider - eventLogProvider.service = this; + eventLogProvider.Service = this; } - public WrapperService() : this(new ServiceDescriptor()) + public WrapperService() + : this(new ServiceDescriptor()) { } @@ -77,9 +79,11 @@ namespace winsw /// private void HandleFileCopies() { - var file = _descriptor.BasePath + ".copies"; + var file = this.descriptor.BasePath + ".copies"; if (!File.Exists(file)) + { return; // nothing to handle + } try { @@ -87,15 +91,15 @@ namespace winsw string? line; while ((line = tr.ReadLine()) != null) { - LogEvent("Handling copy: " + line); + this.LogEvent("Handling copy: " + line); string[] tokens = line.Split('>'); if (tokens.Length > 2) { - LogEvent("Too many delimiters in " + line); + this.LogEvent("Too many delimiters in " + line); continue; } - MoveFile(tokens[0], tokens[1]); + this.MoveFile(tokens[0], tokens[1]); } } finally @@ -115,7 +119,7 @@ namespace winsw } catch (IOException e) { - LogEvent("Failed to move :" + sourceFileName + " to " + destFileName + " because " + e.Message); + this.LogEvent("Failed to move :" + sourceFileName + " to " + destFileName + " because " + e.Message); } } @@ -125,21 +129,21 @@ namespace winsw /// Log Handler, which should be used for the spawned process private LogHandler CreateExecutableLogHandler() { - string logDirectory = _descriptor.LogDirectory; + string logDirectory = this.descriptor.LogDirectory; if (!Directory.Exists(logDirectory)) { Directory.CreateDirectory(logDirectory); } - LogHandler logAppender = _descriptor.LogHandler; + LogHandler logAppender = this.descriptor.LogHandler; logAppender.EventLogger = this; return logAppender; } public void LogEvent(string message) { - if (_systemShuttingdown) + if (this.systemShuttingdown) { /* NOP - cannot call EventLog because of shutdown. */ } @@ -147,7 +151,7 @@ namespace winsw { try { - EventLog.WriteEntry(message); + this.EventLog.WriteEntry(message); } catch (Exception e) { @@ -158,7 +162,7 @@ namespace winsw public void LogEvent(string message, EventLogEntryType type) { - if (_systemShuttingdown) + if (this.systemShuttingdown) { /* NOP - cannot call EventLog because of shutdown. */ } @@ -166,7 +170,7 @@ namespace winsw { try { - EventLog.WriteEntry(message, type); + this.EventLog.WriteEntry(message, type); } catch (Exception e) { @@ -177,24 +181,18 @@ namespace winsw protected override void OnStart(string[] args) { - _envs = _descriptor.EnvironmentVariables; - // TODO: Disabled according to security concerns in https://github.com/kohsuke/winsw/issues/54 - // Could be restored, but unlikely it's required in event logs at all - /** - foreach (string key in _envs.Keys) - { - LogEvent("envar " + key + '=' + _envs[key]); - }*/ - HandleFileCopies(); + this.envs = this.descriptor.EnvironmentVariables; + + this.HandleFileCopies(); // handle downloads - List downloads = _descriptor.Downloads; + List downloads = this.descriptor.Downloads; Task[] tasks = new Task[downloads.Count]; for (int i = 0; i < downloads.Count; i++) { Download download = downloads[i]; string downloadMessage = $"Downloading: {download.From} to {download.To}. failOnError={download.FailOnError.ToString()}"; - LogEvent(downloadMessage); + this.LogEvent(downloadMessage); Log.Info(downloadMessage); tasks[i] = download.PerformAsync(); } @@ -213,7 +211,7 @@ namespace winsw Download download = downloads[i]; string errorMessage = $"Failed to download {download.From} to {download.To}"; AggregateException exception = tasks[i].Exception!; - LogEvent($"{errorMessage}. {exception.Message}"); + this.LogEvent($"{errorMessage}. {exception.Message}"); Log.Error(errorMessage, exception); // TODO: move this code into the download logic @@ -227,34 +225,34 @@ namespace winsw throw new AggregateException(exceptions); } - string? startArguments = _descriptor.StartArguments; + string? startArguments = this.descriptor.StartArguments; if (startArguments is null) { - startArguments = _descriptor.Arguments; + startArguments = this.descriptor.Arguments; } else { - startArguments += " " + _descriptor.Arguments; + startArguments += " " + this.descriptor.Arguments; } - // Converting newlines, line returns, tabs into a single + // Converting newlines, line returns, tabs into a single // space. This allows users to provide multi-line arguments // in the xml for readability. startArguments = Regex.Replace(startArguments, @"\s*[\n\r]+\s*", " "); - LogEvent("Starting " + _descriptor.Executable + ' ' + startArguments); - Log.Info("Starting " + _descriptor.Executable + ' ' + startArguments); + this.LogEvent("Starting " + this.descriptor.Executable + ' ' + startArguments); + Log.Info("Starting " + this.descriptor.Executable + ' ' + startArguments); // Load and start extensions - ExtensionManager.LoadExtensions(); - ExtensionManager.FireOnWrapperStarted(); + this.ExtensionManager.LoadExtensions(); + this.ExtensionManager.FireOnWrapperStarted(); - LogHandler executableLogHandler = CreateExecutableLogHandler(); - StartProcess(_process, startArguments, _descriptor.Executable, executableLogHandler, true); - ExtensionManager.FireOnProcessStarted(_process); + LogHandler executableLogHandler = this.CreateExecutableLogHandler(); + this.StartProcess(this.process, startArguments, this.descriptor.Executable, executableLogHandler, true); + this.ExtensionManager.FireOnProcessStarted(this.process); - _process.StandardInput.Close(); // nothing for you to read! + this.process.StandardInput.Close(); // nothing for you to read! } protected override void OnShutdown() @@ -263,8 +261,8 @@ namespace winsw try { - _systemShuttingdown = true; - StopIt(); + this.systemShuttingdown = true; + this.StopIt(); } catch (Exception ex) { @@ -278,7 +276,7 @@ namespace winsw try { - StopIt(); + this.StopIt(); } catch (Exception ex) { @@ -295,18 +293,18 @@ namespace winsw /// private void StopIt() { - string? stopArguments = _descriptor.StopArguments; - LogEvent("Stopping " + _descriptor.Id); - Log.Info("Stopping " + _descriptor.Id); - _orderlyShutdown = true; + string? stopArguments = this.descriptor.StopArguments; + this.LogEvent("Stopping " + this.descriptor.Id); + Log.Info("Stopping " + this.descriptor.Id); + this.orderlyShutdown = true; if (stopArguments is null) { try { - Log.Debug("ProcessKill " + _process.Id); - ProcessHelper.StopProcessTree(_process, _descriptor.StopTimeout); - ExtensionManager.FireOnProcessTerminated(_process); + Log.Debug("ProcessKill " + this.process.Id); + ProcessHelper.StopProcessTree(this.process, this.descriptor.StopTimeout); + this.ExtensionManager.FireOnProcessTerminated(this.process); } catch (InvalidOperationException) { @@ -315,48 +313,48 @@ namespace winsw } else { - SignalShutdownPending(); + this.SignalShutdownPending(); - stopArguments += " " + _descriptor.Arguments; + stopArguments += " " + this.descriptor.Arguments; Process stopProcess = new Process(); - string? executable = _descriptor.StopExecutable; + string? executable = this.descriptor.StopExecutable; - executable ??= _descriptor.Executable; + executable ??= this.descriptor.Executable; // TODO: Redirect logging to Log4Net once https://github.com/kohsuke/winsw/pull/213 is integrated - StartProcess(stopProcess, stopArguments, executable, null, false); + this.StartProcess(stopProcess, stopArguments, executable, null, false); - Log.Debug("WaitForProcessToExit " + _process.Id + "+" + stopProcess.Id); - WaitForProcessToExit(_process); - WaitForProcessToExit(stopProcess); + Log.Debug("WaitForProcessToExit " + this.process.Id + "+" + stopProcess.Id); + this.WaitForProcessToExit(this.process); + this.WaitForProcessToExit(stopProcess); } // Stop extensions - ExtensionManager.FireBeforeWrapperStopped(); + this.ExtensionManager.FireBeforeWrapperStopped(); - if (_systemShuttingdown && _descriptor.BeepOnShutdown) + if (this.systemShuttingdown && this.descriptor.BeepOnShutdown) { Console.Beep(); } - Log.Info("Finished " + _descriptor.Id); + Log.Info("Finished " + this.descriptor.Id); } private void WaitForProcessToExit(Process processoWait) { - SignalShutdownPending(); + this.SignalShutdownPending(); int effectiveProcessWaitSleepTime; - if (_descriptor.SleepTime.TotalMilliseconds > int.MaxValue) + if (this.descriptor.SleepTime.TotalMilliseconds > int.MaxValue) { - Log.Warn("The requested sleep time " + _descriptor.SleepTime.TotalMilliseconds + "is greater that the max value " + + Log.Warn("The requested sleep time " + this.descriptor.SleepTime.TotalMilliseconds + "is greater that the max value " + int.MaxValue + ". The value will be truncated"); effectiveProcessWaitSleepTime = int.MaxValue; } else { - effectiveProcessWaitSleepTime = (int)_descriptor.SleepTime.TotalMilliseconds; + effectiveProcessWaitSleepTime = (int)this.descriptor.SleepTime.TotalMilliseconds; } try @@ -365,7 +363,7 @@ namespace winsw while (!processoWait.WaitForExit(effectiveProcessWaitSleepTime)) { - SignalShutdownPending(); + this.SignalShutdownPending(); // WriteEvent("WaitForProcessToExit [repeat]"); } } @@ -380,27 +378,27 @@ namespace winsw private void SignalShutdownPending() { int effectiveWaitHint; - if (_descriptor.WaitHint.TotalMilliseconds > int.MaxValue) + if (this.descriptor.WaitHint.TotalMilliseconds > int.MaxValue) { - Log.Warn("The requested WaitHint value (" + _descriptor.WaitHint.TotalMilliseconds + " ms) is greater that the max value " + + Log.Warn("The requested WaitHint value (" + this.descriptor.WaitHint.TotalMilliseconds + " ms) is greater that the max value " + int.MaxValue + ". The value will be truncated"); effectiveWaitHint = int.MaxValue; } else { - effectiveWaitHint = (int)_descriptor.WaitHint.TotalMilliseconds; + effectiveWaitHint = (int)this.descriptor.WaitHint.TotalMilliseconds; } - RequestAdditionalTime(effectiveWaitHint); + this.RequestAdditionalTime(effectiveWaitHint); } private void SignalShutdownComplete() { - IntPtr handle = ServiceHandle; - _wrapperServiceStatus.CheckPoint++; + IntPtr handle = this.ServiceHandle; + this.wrapperServiceStatus.CheckPoint++; // WriteEvent("SignalShutdownComplete " + wrapperServiceStatus.checkPoint + ":" + wrapperServiceStatus.waitHint); - _wrapperServiceStatus.CurrentState = ServiceControllerStatus.Stopped; - ServiceApis.SetServiceStatus(handle, _wrapperServiceStatus); + this.wrapperServiceStatus.CurrentState = ServiceControllerStatus.Stopped; + ServiceApis.SetServiceStatus(handle, this.wrapperServiceStatus); } private void StartProcess(Process processToStart, string arguments, string executable, LogHandler? logHandler, bool redirectStdin) @@ -411,25 +409,28 @@ namespace winsw string msg = processToStart.Id + " - " + processToStart.StartInfo.FileName + " " + processToStart.StartInfo.Arguments; try { - if (_orderlyShutdown) + if (this.orderlyShutdown) { - LogEvent("Child process [" + msg + "] terminated with " + proc.ExitCode, EventLogEntryType.Information); + this.LogEvent("Child process [" + msg + "] terminated with " + proc.ExitCode, EventLogEntryType.Information); } else { - LogEvent("Child process [" + msg + "] finished with " + proc.ExitCode, EventLogEntryType.Warning); + this.LogEvent("Child process [" + msg + "] finished with " + proc.ExitCode, EventLogEntryType.Warning); + // if we finished orderly, report that to SCM. // by not reporting unclean shutdown, we let Windows SCM to decide if it wants to // restart the service automatically if (proc.ExitCode == 0) - SignalShutdownComplete(); + { + this.SignalShutdownComplete(); + } Environment.Exit(proc.ExitCode); } } catch (InvalidOperationException ioe) { - LogEvent("WaitForExit " + ioe.Message); + this.LogEvent("WaitForExit " + ioe.Message); } finally { @@ -442,13 +443,13 @@ namespace winsw processToStart: processToStart, executable: executable, arguments: arguments, - envVars: _envs, - workingDirectory: _descriptor.WorkingDirectory, - priority: _descriptor.Priority, + envVars: this.envs, + workingDirectory: this.descriptor.WorkingDirectory, + priority: this.descriptor.Priority, callback: OnProcessCompleted, logHandler: logHandler, redirectStdin: redirectStdin, - hideWindow: _descriptor.HideWindow); + hideWindow: this.descriptor.HideWindow); } } } diff --git a/src/Core/WinSWCore/Configuration/DefaultSettings.cs b/src/Core/WinSWCore/Configuration/DefaultSettings.cs index 128eb63..0b8d49b 100644 --- a/src/Core/WinSWCore/Configuration/DefaultSettings.cs +++ b/src/Core/WinSWCore/Configuration/DefaultSettings.cs @@ -5,56 +5,80 @@ using System.IO; using System.ServiceProcess; using System.Xml; -namespace winsw.Configuration +namespace WinSW.Configuration { /// /// Default WinSW settings /// public sealed class DefaultWinSWSettings : IWinSWConfiguration { - public string Id => throw new InvalidOperationException(nameof(Id) + " must be specified."); - public string Caption => throw new InvalidOperationException(nameof(Caption) + " must be specified."); - public string Description => throw new InvalidOperationException(nameof(Description) + " must be specified."); - public string Executable => throw new InvalidOperationException(nameof(Executable) + " must be specified."); + public string Id => throw new InvalidOperationException(nameof(this.Id) + " must be specified."); + + public string Caption => throw new InvalidOperationException(nameof(this.Caption) + " must be specified."); + + public string Description => throw new InvalidOperationException(nameof(this.Description) + " must be specified."); + + 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(ExecutablePath)!; + + public string WorkingDirectory => Path.GetDirectoryName(this.ExecutablePath)!; + public ProcessPriorityClass Priority => ProcessPriorityClass.Normal; + public TimeSpan StopTimeout => TimeSpan.FromSeconds(15); // Service management public ServiceStartMode StartMode => ServiceStartMode.Automatic; + public bool DelayedAutoStart => false; + public string[] ServiceDependencies => new string[0]; + public TimeSpan WaitHint => TimeSpan.FromSeconds(15); + public TimeSpan SleepTime => TimeSpan.FromSeconds(1); + public bool Interactive => false; // Logging - public string LogDirectory => Path.GetDirectoryName(ExecutablePath)!; + 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 diff --git a/src/Core/WinSWCore/Configuration/IWinSWConfiguration.cs b/src/Core/WinSWCore/Configuration/IWinSWConfiguration.cs index ae7cd4b..4ad0221 100644 --- a/src/Core/WinSWCore/Configuration/IWinSWConfiguration.cs +++ b/src/Core/WinSWCore/Configuration/IWinSWConfiguration.cs @@ -4,49 +4,69 @@ using System.Diagnostics; using System.ServiceProcess; using System.Xml; -namespace winsw.Configuration +namespace WinSW.Configuration { + // TODO: Document the parameters && refactor public interface IWinSWConfiguration { - // TODO: Document the parameters && refactor - 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; } + TimeSpan WaitHint { get; } + TimeSpan SleepTime { get; } + bool Interactive { get; } // Logging string LogDirectory { get; } + // TODO: replace by enum string LogMode { get; } // Environment List Downloads { get; } + Dictionary EnvironmentVariables { get; } // Misc diff --git a/src/Core/WinSWCore/Download.cs b/src/Core/WinSWCore/Download.cs index 9673a2c..5f2a13b 100755 --- a/src/Core/WinSWCore/Download.cs +++ b/src/Core/WinSWCore/Download.cs @@ -5,9 +5,9 @@ using System.Text; using System.Threading.Tasks; using System.Xml; using log4net; -using winsw.Util; +using WinSW.Util; -namespace winsw +namespace WinSW { /// /// Specify the download activities prior to the launch. @@ -17,9 +17,9 @@ namespace winsw { public enum AuthType { - none = 0, - sspi, - basic + None = 0, + Sspi, + Basic } private static readonly ILog Logger = LogManager.GetLogger(typeof(Download)); @@ -33,7 +33,7 @@ namespace winsw public readonly bool FailOnError; public readonly string? Proxy; - public string ShortId => $"(download from {From})"; + public string ShortId => $"(download from {this.From})"; #if NET461 static Download() @@ -48,20 +48,20 @@ namespace winsw string from, string to, bool failOnError = false, - AuthType auth = AuthType.none, + AuthType auth = AuthType.None, string? username = null, string? password = null, bool unsecureAuth = false, string? proxy = null) { - From = from; - To = to; - FailOnError = failOnError; - Proxy = proxy; - Auth = auth; - Username = username; - Password = password; - UnsecureAuth = unsecureAuth; + this.From = from; + this.To = to; + this.FailOnError = failOnError; + this.Proxy = proxy; + this.Auth = auth; + this.Username = username; + this.Password = password; + this.UnsecureAuth = unsecureAuth; } /// @@ -71,36 +71,36 @@ namespace winsw /// The required attribute is missing or the configuration is invalid internal Download(XmlElement n) { - From = XmlHelper.SingleAttribute(n, "from"); - To = XmlHelper.SingleAttribute(n, "to"); + this.From = XmlHelper.SingleAttribute(n, "from"); + this.To = XmlHelper.SingleAttribute(n, "to"); // All arguments below are optional - FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false); - Proxy = XmlHelper.SingleAttribute(n, "proxy", null); + this.FailOnError = XmlHelper.SingleAttribute(n, "failOnError", false); + this.Proxy = XmlHelper.SingleAttribute(n, "proxy", null); - Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.none); - Username = XmlHelper.SingleAttribute(n, "user", null); - Password = XmlHelper.SingleAttribute(n, "password", null); - UnsecureAuth = XmlHelper.SingleAttribute(n, "unsecureAuth", false); + this.Auth = XmlHelper.EnumAttribute(n, "auth", AuthType.None); + this.Username = XmlHelper.SingleAttribute(n, "user", null); + this.Password = XmlHelper.SingleAttribute(n, "password", null); + this.UnsecureAuth = XmlHelper.SingleAttribute(n, "unsecureAuth", false); - if (Auth == AuthType.basic) + if (this.Auth == AuthType.Basic) { // Allow it only for HTTPS or for UnsecureAuth - if (!From.StartsWith("https:") && !UnsecureAuth) + if (!this.From.StartsWith("https:") && !this.UnsecureAuth) { - throw new InvalidDataException("Warning: you're sending your credentials in clear text to the server " + ShortId + + throw new InvalidDataException("Warning: you're sending your credentials in clear text to the server " + this.ShortId + "If you really want this you must enable 'unsecureAuth' in the configuration"); } // Also fail if there is no user/password - if (Username is null) + if (this.Username is null) { - throw new InvalidDataException("Basic Auth is enabled, but username is not specified " + ShortId); + throw new InvalidDataException("Basic Auth is enabled, but username is not specified " + this.ShortId); } - if (Password is null) + if (this.Password is null) { - throw new InvalidDataException("Basic Auth is enabled, but password is not specified " + ShortId); + throw new InvalidDataException("Basic Auth is enabled, but password is not specified " + this.ShortId); } } } @@ -121,10 +121,10 @@ namespace winsw /// public async Task PerformAsync() { - WebRequest request = WebRequest.Create(From); - if (!string.IsNullOrEmpty(Proxy)) + WebRequest request = WebRequest.Create(this.From); + if (!string.IsNullOrEmpty(this.Proxy)) { - CustomProxyInformation proxyInformation = new CustomProxyInformation(Proxy); + CustomProxyInformation proxyInformation = new CustomProxyInformation(this.Proxy!); if (proxyInformation.Credentials != null) { request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials); @@ -135,35 +135,35 @@ namespace winsw } } - switch (Auth) + switch (this.Auth) { - case AuthType.none: + case AuthType.None: // Do nothing break; - case AuthType.sspi: + case AuthType.Sspi: request.UseDefaultCredentials = true; request.PreAuthenticate = true; request.Credentials = CredentialCache.DefaultCredentials; break; - case AuthType.basic: - SetBasicAuthHeader(request, Username!, Password!); + case AuthType.Basic: + this.SetBasicAuthHeader(request, this.Username!, this.Password!); break; default: - throw new WebException("Code defect. Unsupported authentication type: " + Auth); + throw new WebException("Code defect. Unsupported authentication type: " + this.Auth); } bool supportsIfModifiedSince = false; - if (request is HttpWebRequest httpRequest && File.Exists(To)) + if (request is HttpWebRequest httpRequest && File.Exists(this.To)) { supportsIfModifiedSince = true; - httpRequest.IfModifiedSince = File.GetLastWriteTime(To); + httpRequest.IfModifiedSince = File.GetLastWriteTime(this.To); } DateTime lastModified = default; - string tmpFilePath = To + ".tmp"; + string tmpFilePath = this.To + ".tmp"; try { using (WebResponse response = await request.GetResponseAsync()) @@ -178,18 +178,18 @@ namespace winsw await responseStream.CopyToAsync(tmpStream); } - FileHelper.MoveOrReplaceFile(To + ".tmp", To); + FileHelper.MoveOrReplaceFile(this.To + ".tmp", this.To); if (supportsIfModifiedSince) { - File.SetLastWriteTime(To, lastModified); + File.SetLastWriteTime(this.To, lastModified); } } catch (WebException e) { if (supportsIfModifiedSince && ((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified) { - Logger.Info($"Skipped downloading unmodified resource '{From}'"); + Logger.Info($"Skipped downloading unmodified resource '{this.From}'"); } else { @@ -201,8 +201,9 @@ namespace winsw public class CustomProxyInformation { - public string ServerAddress { get; set; } - public NetworkCredential? Credentials { get; set; } + public string ServerAddress { get; } + + public NetworkCredential? Credentials { get; } public CustomProxyInformation(string proxy) { @@ -216,12 +217,12 @@ namespace winsw string username = completeCredsStr.Substring(0, credsSeparator); string password = completeCredsStr.Substring(credsSeparator + 1); - Credentials = new NetworkCredential(username, password); - ServerAddress = proxy.Replace(completeCredsStr + "@", ""); + this.Credentials = new NetworkCredential(username, password); + this.ServerAddress = proxy.Replace(completeCredsStr + "@", null); } else { - ServerAddress = proxy; + this.ServerAddress = proxy; } } } diff --git a/src/Core/WinSWCore/Extensions/AbstractWinSWExtension.cs b/src/Core/WinSWCore/Extensions/AbstractWinSWExtension.cs index 5173e84..bfc5f4a 100644 --- a/src/Core/WinSWCore/Extensions/AbstractWinSWExtension.cs +++ b/src/Core/WinSWCore/Extensions/AbstractWinSWExtension.cs @@ -1,6 +1,6 @@ using System.Xml; -namespace winsw.Extensions +namespace WinSW.Extensions { public abstract class AbstractWinSWExtension : IWinSWExtension { diff --git a/src/Core/WinSWCore/Extensions/ExtensionException.cs b/src/Core/WinSWCore/Extensions/ExtensionException.cs index 48a5ae2..19fc041 100644 --- a/src/Core/WinSWCore/Extensions/ExtensionException.cs +++ b/src/Core/WinSWCore/Extensions/ExtensionException.cs @@ -1,23 +1,23 @@ using System; -namespace winsw.Extensions +namespace WinSW.Extensions { public class ExtensionException : WinSWException { - public string ExtensionId { get; private set; } + public string ExtensionId { get; } public ExtensionException(string extensionName, string message) : base(message) { - ExtensionId = extensionName; + this.ExtensionId = extensionName; } public ExtensionException(string extensionName, string message, Exception innerException) : base(message, innerException) { - ExtensionId = extensionName; + this.ExtensionId = extensionName; } - public override string Message => ExtensionId + ": " + base.Message; + public override string Message => this.ExtensionId + ": " + base.Message; } } diff --git a/src/Core/WinSWCore/Extensions/ExtensionPointAttribute.cs b/src/Core/WinSWCore/Extensions/ExtensionPointAttribute.cs deleted file mode 100644 index fd51b4d..0000000 --- a/src/Core/WinSWCore/Extensions/ExtensionPointAttribute.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace winsw.Extensions -{ - /// - /// This attribute is used to identify extension points within the code - /// - /// - /// Each extension point implements its own entry type. - /// - class ExtensionPointAttribute - { - } -} diff --git a/src/Core/WinSWCore/Extensions/IWinSWExtension.cs b/src/Core/WinSWCore/Extensions/IWinSWExtension.cs index e10819a..a7c1f35 100644 --- a/src/Core/WinSWCore/Extensions/IWinSWExtension.cs +++ b/src/Core/WinSWCore/Extensions/IWinSWExtension.cs @@ -1,6 +1,6 @@ using System.Xml; -namespace winsw.Extensions +namespace WinSW.Extensions { /// /// Interface for Win Service Wrapper Extension diff --git a/src/Core/WinSWCore/Extensions/WinSWExtensionDescriptor.cs b/src/Core/WinSWCore/Extensions/WinSWExtensionDescriptor.cs index 60fe91a..5e77869 100644 --- a/src/Core/WinSWCore/Extensions/WinSWExtensionDescriptor.cs +++ b/src/Core/WinSWCore/Extensions/WinSWExtensionDescriptor.cs @@ -1,7 +1,7 @@ using System.Xml; -using winsw.Util; +using WinSW.Util; -namespace winsw.Extensions +namespace WinSW.Extensions { /// /// Describes WinSW extensions in @@ -14,23 +14,23 @@ namespace winsw.Extensions /// /// Unique extension ID /// - public string Id { get; private set; } + public string Id { get; } /// /// Exception is enabled /// - public bool Enabled { get; private set; } + public bool Enabled { get; } /// /// Extension classname /// - public string ClassName { get; private set; } + public string ClassName { get; } private WinSWExtensionDescriptor(string id, string className, bool enabled) { - Id = id; - Enabled = enabled; - ClassName = className; + this.Id = id; + this.Enabled = enabled; + this.ClassName = className; } public static WinSWExtensionDescriptor FromXml(XmlElement node) diff --git a/src/Core/WinSWCore/Extensions/WinSWExtensionManager.cs b/src/Core/WinSWCore/Extensions/WinSWExtensionManager.cs index d182875..1ecb90b 100644 --- a/src/Core/WinSWCore/Extensions/WinSWExtensionManager.cs +++ b/src/Core/WinSWCore/Extensions/WinSWExtensionManager.cs @@ -3,20 +3,20 @@ using System.Collections.Generic; using System.Xml; using log4net; -namespace winsw.Extensions +namespace WinSW.Extensions { public class WinSWExtensionManager { - public Dictionary Extensions { get; private set; } + public Dictionary Extensions { get; } - public ServiceDescriptor ServiceDescriptor { get; private set; } + public ServiceDescriptor ServiceDescriptor { get; } private static readonly ILog Log = LogManager.GetLogger(typeof(WinSWExtensionManager)); public WinSWExtensionManager(ServiceDescriptor serviceDescriptor) { - ServiceDescriptor = serviceDescriptor; - Extensions = new Dictionary(); + this.ServiceDescriptor = serviceDescriptor; + this.Extensions = new Dictionary(); } /// @@ -27,7 +27,7 @@ namespace winsw.Extensions /// Start failure public void FireOnWrapperStarted() { - foreach (var ext in Extensions) + foreach (var ext in this.Extensions) { try { @@ -47,7 +47,7 @@ namespace winsw.Extensions /// public void FireBeforeWrapperStopped() { - foreach (var ext in Extensions) + foreach (var ext in this.Extensions) { try { @@ -66,7 +66,7 @@ namespace winsw.Extensions /// Process public void FireOnProcessStarted(System.Diagnostics.Process process) { - foreach (var ext in Extensions) + foreach (var ext in this.Extensions) { try { @@ -85,7 +85,7 @@ namespace winsw.Extensions /// Process public void FireOnProcessTerminated(System.Diagnostics.Process process) { - foreach (var ext in Extensions) + foreach (var ext in this.Extensions) { try { @@ -107,10 +107,10 @@ namespace winsw.Extensions /// Loading failure public void LoadExtensions() { - var extensionIds = ServiceDescriptor.ExtensionIds; + var extensionIds = this.ServiceDescriptor.ExtensionIds; foreach (string extensionId in extensionIds) { - LoadExtension(extensionId); + this.LoadExtension(extensionId); } } @@ -122,12 +122,12 @@ namespace winsw.Extensions /// Loading failure private void LoadExtension(string id) { - if (Extensions.ContainsKey(id)) + if (this.Extensions.ContainsKey(id)) { throw new ExtensionException(id, "Extension has been already loaded"); } - XmlNode? extensionsConfig = ServiceDescriptor.ExtensionsConfiguration; + XmlNode? extensionsConfig = this.ServiceDescriptor.ExtensionsConfiguration; XmlElement? configNode = extensionsConfig is null ? null : extensionsConfig.SelectSingleNode("extension[@id='" + id + "'][1]") as XmlElement; if (configNode is null) { @@ -137,11 +137,11 @@ namespace winsw.Extensions var descriptor = WinSWExtensionDescriptor.FromXml(configNode); if (descriptor.Enabled) { - IWinSWExtension extension = CreateExtensionInstance(descriptor.Id, descriptor.ClassName); + IWinSWExtension extension = this.CreateExtensionInstance(descriptor.Id, descriptor.ClassName); extension.Descriptor = descriptor; try { - extension.Configure(ServiceDescriptor, configNode); + extension.Configure(this.ServiceDescriptor, configNode); } catch (Exception ex) { // Consider any unexpected exception as fatal @@ -149,7 +149,7 @@ namespace winsw.Extensions throw ex; } - Extensions.Add(id, extension); + this.Extensions.Add(id, extension); Log.Info("Extension loaded: " + id); } else diff --git a/src/Core/WinSWCore/LogAppenders.cs b/src/Core/WinSWCore/LogAppenders.cs index fa8e764..0809b1a 100644 --- a/src/Core/WinSWCore/LogAppenders.cs +++ b/src/Core/WinSWCore/LogAppenders.cs @@ -1,14 +1,13 @@ using System; using System.Diagnostics; -using System.IO.Compression; using System.IO; +using System.IO.Compression; using System.Threading; -using winsw.Util; +using WinSW.Util; -namespace winsw +namespace WinSW { - // ReSharper disable once InconsistentNaming - public interface EventLogger + public interface IEventLogger { void LogEvent(string message); @@ -20,14 +19,13 @@ namespace winsw /// public abstract class LogHandler { - // ReSharper disable once InconsistentNaming - public abstract void log(StreamReader outputReader, StreamReader errorReader); + public abstract void Log(StreamReader outputReader, StreamReader errorReader); /// /// Error and information about logging should be reported here. /// #pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. - public EventLogger EventLogger { get; set; } + public IEventLogger EventLogger { get; set; } #pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. /// @@ -56,7 +54,7 @@ namespace winsw } catch (IOException e) { - EventLogger.LogEvent("Failed to move :" + sourceFileName + " to " + destFileName + " because " + e.Message); + this.EventLogger.LogEvent("Failed to move :" + sourceFileName + " to " + destFileName + " because " + e.Message); } } } @@ -66,22 +64,26 @@ namespace winsw /// public abstract class AbstractFileLogAppender : LogHandler { - protected string BaseLogFileName { get; private set; } - protected bool OutFileDisabled { get; private set; } - protected bool ErrFileDisabled { get; private set; } - protected string OutFilePattern { get; private set; } - protected string ErrFilePattern { get; private set; } + protected string BaseLogFileName { get; } + + protected bool OutFileDisabled { get; } + + protected bool ErrFileDisabled { get; } + + protected string OutFilePattern { get; } + + protected string ErrFilePattern { get; } protected AbstractFileLogAppender(string logDirectory, string baseName, bool outFileDisabled, bool errFileDisabled, string outFilePattern, string errFilePattern) { - BaseLogFileName = Path.Combine(logDirectory, baseName); - OutFileDisabled = outFileDisabled; - OutFilePattern = outFilePattern; - ErrFileDisabled = errFileDisabled; - ErrFilePattern = errFilePattern; + this.BaseLogFileName = Path.Combine(logDirectory, baseName); + this.OutFileDisabled = outFileDisabled; + this.OutFilePattern = outFilePattern; + this.ErrFileDisabled = errFileDisabled; + this.ErrFilePattern = errFilePattern; } - public override void log(StreamReader outputReader, StreamReader errorReader) + public override void Log(StreamReader outputReader, StreamReader errorReader) { if (this.OutFileDisabled) { @@ -111,26 +113,28 @@ namespace winsw public abstract class SimpleLogAppender : AbstractFileLogAppender { - public FileMode FileMode { get; private set; } - public string OutputLogFileName { get; private set; } - public string ErrorLogFileName { get; private set; } + public FileMode FileMode { get; } + + public string OutputLogFileName { get; } + + public string ErrorLogFileName { get; } protected SimpleLogAppender(string logDirectory, string baseName, FileMode fileMode, bool outFileDisabled, bool errFileDisabled, string outFilePattern, string errFilePattern) : base(logDirectory, baseName, outFileDisabled, errFileDisabled, outFilePattern, errFilePattern) { - FileMode = fileMode; - OutputLogFileName = BaseLogFileName + ".out.log"; - ErrorLogFileName = BaseLogFileName + ".err.log"; + this.FileMode = fileMode; + this.OutputLogFileName = this.BaseLogFileName + ".out.log"; + this.ErrorLogFileName = this.BaseLogFileName + ".err.log"; } protected override void LogOutput(StreamReader outputReader) { - new Thread(() => CopyStream(outputReader, CreateWriter(new FileStream(OutputLogFileName, FileMode)))).Start(); + new Thread(() => this.CopyStream(outputReader, this.CreateWriter(new FileStream(this.OutputLogFileName, this.FileMode)))).Start(); } protected override void LogError(StreamReader errorReader) { - new Thread(() => CopyStream(errorReader, CreateWriter(new FileStream(ErrorLogFileName, FileMode)))).Start(); + new Thread(() => this.CopyStream(errorReader, this.CreateWriter(new FileStream(this.ErrorLogFileName, this.FileMode)))).Start(); } } @@ -155,7 +159,7 @@ namespace winsw /// public class IgnoreLogAppender : LogHandler { - public override void log(StreamReader outputReader, StreamReader errorReader) + public override void Log(StreamReader outputReader, StreamReader errorReader) { outputReader.Dispose(); errorReader.Dispose(); @@ -164,24 +168,25 @@ namespace winsw public class TimeBasedRollingLogAppender : AbstractFileLogAppender { - public string Pattern { get; private set; } - public int Period { get; private set; } + public string Pattern { get; } + + public int Period { get; } public TimeBasedRollingLogAppender(string logDirectory, string baseName, bool outFileDisabled, bool errFileDisabled, string outFilePattern, string errFilePattern, string pattern, int period) : base(logDirectory, baseName, outFileDisabled, errFileDisabled, outFilePattern, errFilePattern) { - Pattern = pattern; - Period = period; + this.Pattern = pattern; + this.Period = period; } protected override void LogOutput(StreamReader outputReader) { - new Thread(() => CopyStreamWithDateRotation(outputReader, OutFilePattern)).Start(); + new Thread(() => this.CopyStreamWithDateRotation(outputReader, this.OutFilePattern)).Start(); } protected override void LogError(StreamReader errorReader) { - new Thread(() => CopyStreamWithDateRotation(errorReader, ErrFilePattern)).Start(); + new Thread(() => this.CopyStreamWithDateRotation(errorReader, this.ErrFilePattern)).Start(); } /// @@ -189,17 +194,17 @@ namespace winsw /// private void CopyStreamWithDateRotation(StreamReader reader, string ext) { - PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(Pattern, Period); - periodicRollingCalendar.init(); + PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.Pattern, this.Period); + periodicRollingCalendar.Init(); - StreamWriter writer = CreateWriter(new FileStream(BaseLogFileName + "_" + periodicRollingCalendar.format + ext, FileMode.Append)); + StreamWriter writer = this.CreateWriter(new FileStream(this.BaseLogFileName + "_" + periodicRollingCalendar.Format + ext, FileMode.Append)); string? line; while ((line = reader.ReadLine()) != null) { - if (periodicRollingCalendar.shouldRoll) + if (periodicRollingCalendar.ShouldRoll) { writer.Dispose(); - writer = CreateWriter(new FileStream(BaseLogFileName + "_" + periodicRollingCalendar.format + ext, FileMode.Create)); + writer = this.CreateWriter(new FileStream(this.BaseLogFileName + "_" + periodicRollingCalendar.Format + ext, FileMode.Create)); } writer.WriteLine(line); @@ -212,37 +217,35 @@ namespace winsw public class SizeBasedRollingLogAppender : AbstractFileLogAppender { - // ReSharper disable once InconsistentNaming - public static int BYTES_PER_KB = 1024; - // ReSharper disable once InconsistentNaming - public static int BYTES_PER_MB = 1024 * BYTES_PER_KB; - // ReSharper disable once InconsistentNaming - public static int DEFAULT_SIZE_THRESHOLD = 10 * BYTES_PER_MB; // roll every 10MB. - // ReSharper disable once InconsistentNaming - public static int DEFAULT_FILES_TO_KEEP = 8; + public const int BytesPerKB = 1024; + public const int BytesPerMB = 1024 * BytesPerKB; + public const int DefaultSizeThreshold = 10 * BytesPerMB; // roll every 10MB. + public const int DefaultFilesToKeep = 8; - public int SizeTheshold { get; private set; } + public int SizeThreshold { get; } - public int FilesToKeep { get; private set; } + public int FilesToKeep { get; } public SizeBasedRollingLogAppender(string logDirectory, string baseName, bool outFileDisabled, bool errFileDisabled, string outFilePattern, string errFilePattern, int sizeThreshold, int filesToKeep) : base(logDirectory, baseName, outFileDisabled, errFileDisabled, outFilePattern, errFilePattern) { - SizeTheshold = sizeThreshold; - FilesToKeep = filesToKeep; + this.SizeThreshold = sizeThreshold; + this.FilesToKeep = filesToKeep; } public SizeBasedRollingLogAppender(string logDirectory, string baseName, bool outFileDisabled, bool errFileDisabled, string outFilePattern, string errFilePattern) - : this(logDirectory, baseName, outFileDisabled, errFileDisabled, outFilePattern, errFilePattern, DEFAULT_SIZE_THRESHOLD, DEFAULT_FILES_TO_KEEP) { } + : this(logDirectory, baseName, outFileDisabled, errFileDisabled, outFilePattern, errFilePattern, DefaultSizeThreshold, DefaultFilesToKeep) + { + } protected override void LogOutput(StreamReader outputReader) { - new Thread(() => CopyStreamWithRotation(outputReader, OutFilePattern)).Start(); + new Thread(() => this.CopyStreamWithRotation(outputReader, this.OutFilePattern)).Start(); } protected override void LogError(StreamReader errorReader) { - new Thread(() => CopyStreamWithRotation(errorReader, ErrFilePattern)).Start(); + new Thread(() => this.CopyStreamWithRotation(errorReader, this.ErrFilePattern)).Start(); } /// @@ -250,41 +253,45 @@ namespace winsw /// private void CopyStreamWithRotation(StreamReader reader, string ext) { - StreamWriter writer = CreateWriter(new FileStream(BaseLogFileName + ext, FileMode.Append)); - long fileLength = new FileInfo(BaseLogFileName + ext).Length; + StreamWriter writer = this.CreateWriter(new FileStream(this.BaseLogFileName + ext, FileMode.Append)); + long fileLength = new FileInfo(this.BaseLogFileName + ext).Length; string? line; while ((line = reader.ReadLine()) != null) { int lengthToWrite = (line.Length + Environment.NewLine.Length) * sizeof(char); - if (fileLength + lengthToWrite > SizeTheshold) + if (fileLength + lengthToWrite > this.SizeThreshold) { writer.Dispose(); try { - for (int j = FilesToKeep; j >= 1; j--) + for (int j = this.FilesToKeep; j >= 1; j--) { - string dst = BaseLogFileName + "." + (j - 1) + ext; - string src = BaseLogFileName + "." + (j - 2) + ext; + string dst = this.BaseLogFileName + "." + (j - 1) + ext; + string src = this.BaseLogFileName + "." + (j - 2) + ext; if (File.Exists(dst)) + { File.Delete(dst); + } if (File.Exists(src)) + { File.Move(src, dst); + } } - File.Move(BaseLogFileName + ext, BaseLogFileName + ".0" + ext); + File.Move(this.BaseLogFileName + ext, this.BaseLogFileName + ".0" + ext); } catch (IOException e) { - EventLogger.LogEvent("Failed to roll log: " + e.Message); + this.EventLogger.LogEvent("Failed to roll log: " + e.Message); } // even if the log rotation fails, create a new one, or else // we'll infinitely try to roll. - writer = CreateWriter(new FileStream(BaseLogFileName + ext, FileMode.Create)); - fileLength = new FileInfo(BaseLogFileName + ext).Length; + writer = this.CreateWriter(new FileStream(this.BaseLogFileName + ext, FileMode.Create)); + fileLength = new FileInfo(this.BaseLogFileName + ext).Length; } writer.WriteLine(line); @@ -306,26 +313,35 @@ namespace winsw { } - public override void log(StreamReader outputReader, StreamReader errorReader) + public override void Log(StreamReader outputReader, StreamReader errorReader) { - if (!OutFileDisabled) - MoveFile(OutputLogFileName, OutputLogFileName + ".old"); + if (!this.OutFileDisabled) + { + this.MoveFile(this.OutputLogFileName, this.OutputLogFileName + ".old"); + } - if (!ErrFileDisabled) - MoveFile(ErrorLogFileName, ErrorLogFileName + ".old"); + if (!this.ErrFileDisabled) + { + this.MoveFile(this.ErrorLogFileName, this.ErrorLogFileName + ".old"); + } - base.log(outputReader, errorReader); + base.Log(outputReader, errorReader); } } public class RollingSizeTimeLogAppender : AbstractFileLogAppender { - public static int BYTES_PER_KB = 1024; - public int SizeTheshold { get; private set; } - public string FilePattern { get; private set; } - public TimeSpan? AutoRollAtTime { get; private set; } - public int? ZipOlderThanNumDays { get; private set; } - public string ZipDateFormat { get; private set; } + public const int BytesPerKB = 1024; + + public int SizeThreshold { get; } + + public string FilePattern { get; } + + public TimeSpan? AutoRollAtTime { get; } + + public int? ZipOlderThanNumDays { get; } + + public string ZipDateFormat { get; } public RollingSizeTimeLogAppender( string logDirectory, @@ -341,21 +357,21 @@ namespace winsw string zipdateformat) : base(logDirectory, baseName, outFileDisabled, errFileDisabled, outFilePattern, errFilePattern) { - SizeTheshold = sizeThreshold; - FilePattern = filePattern; - AutoRollAtTime = autoRollAtTime; - ZipOlderThanNumDays = zipolderthannumdays; - ZipDateFormat = zipdateformat; + this.SizeThreshold = sizeThreshold; + this.FilePattern = filePattern; + this.AutoRollAtTime = autoRollAtTime; + this.ZipOlderThanNumDays = zipolderthannumdays; + this.ZipDateFormat = zipdateformat; } protected override void LogOutput(StreamReader outputReader) { - new Thread(() => CopyStreamWithRotation(outputReader, OutFilePattern)).Start(); + new Thread(() => this.CopyStreamWithRotation(outputReader, this.OutFilePattern)).Start(); } protected override void LogError(StreamReader errorReader) { - new Thread(() => CopyStreamWithRotation(errorReader, ErrFilePattern)).Start(); + new Thread(() => this.CopyStreamWithRotation(errorReader, this.ErrFilePattern)).Start(); } private void CopyStreamWithRotation(StreamReader reader, string extension) @@ -363,18 +379,18 @@ namespace winsw // lock required as the timer thread and the thread that will write to the stream could try and access the file stream at the same time var fileLock = new object(); - var baseDirectory = Path.GetDirectoryName(BaseLogFileName)!; - var baseFileName = Path.GetFileName(BaseLogFileName); - var logFile = BaseLogFileName + extension; + var baseDirectory = Path.GetDirectoryName(this.BaseLogFileName)!; + var baseFileName = Path.GetFileName(this.BaseLogFileName); + var logFile = this.BaseLogFileName + extension; - var writer = CreateWriter(new FileStream(logFile, FileMode.Append)); + var writer = this.CreateWriter(new FileStream(logFile, FileMode.Append)); var fileLength = new FileInfo(logFile).Length; // We auto roll at time is configured then we need to create a timer and wait until time is elasped and roll the file over - if (AutoRollAtTime is TimeSpan autoRollAtTime) + if (this.AutoRollAtTime is TimeSpan autoRollAtTime) { // Run at start - var tickTime = SetupRollTimer(autoRollAtTime); + var tickTime = this.SetupRollTimer(autoRollAtTime); var timer = new System.Timers.Timer(tickTime); timer.Elapsed += (s, e) => { @@ -386,25 +402,25 @@ namespace winsw writer.Dispose(); var now = DateTime.Now.AddDays(-1); - var nextFileNumber = GetNextFileNumber(extension, baseDirectory, baseFileName, now); - var nextFileName = Path.Combine(baseDirectory, string.Format("{0}.{1}.#{2:D4}{3}", baseFileName, now.ToString(FilePattern), nextFileNumber, extension)); + var nextFileNumber = this.GetNextFileNumber(extension, baseDirectory, baseFileName, now); + var nextFileName = Path.Combine(baseDirectory, string.Format("{0}.{1}.#{2:D4}{3}", baseFileName, now.ToString(this.FilePattern), nextFileNumber, extension)); File.Move(logFile, nextFileName); - writer = CreateWriter(new FileStream(logFile, FileMode.Create)); + writer = this.CreateWriter(new FileStream(logFile, FileMode.Create)); fileLength = new FileInfo(logFile).Length; } // Next day so check if file can be zipped - ZipFiles(baseDirectory, extension, baseFileName); + this.ZipFiles(baseDirectory, extension, baseFileName); } catch (Exception ex) { - EventLogger.LogEvent($"Failed to to trigger auto roll at time event due to: {ex.Message}"); + this.EventLogger.LogEvent($"Failed to to trigger auto roll at time event due to: {ex.Message}"); } finally { // Recalculate the next interval - timer.Interval = SetupRollTimer(autoRollAtTime); + timer.Interval = this.SetupRollTimer(autoRollAtTime); timer.Start(); } }; @@ -417,26 +433,26 @@ namespace winsw lock (fileLock) { int lengthToWrite = (line.Length + Environment.NewLine.Length) * sizeof(char); - if (fileLength + lengthToWrite > SizeTheshold) + if (fileLength + lengthToWrite > this.SizeThreshold) { try { // roll file var now = DateTime.Now; - var nextFileNumber = GetNextFileNumber(extension, baseDirectory, baseFileName, now); - var nextFileName = - Path.Combine(baseDirectory, - string.Format("{0}.{1}.#{2:D4}{3}", baseFileName, now.ToString(FilePattern), nextFileNumber, extension)); + var nextFileNumber = this.GetNextFileNumber(extension, baseDirectory, baseFileName, now); + var nextFileName = Path.Combine( + baseDirectory, + string.Format("{0}.{1}.#{2:D4}{3}", baseFileName, now.ToString(this.FilePattern), nextFileNumber, extension)); File.Move(logFile, nextFileName); // even if the log rotation fails, create a new one, or else // we'll infinitely try to roll. - writer = CreateWriter(new FileStream(logFile, FileMode.Create)); + writer = this.CreateWriter(new FileStream(logFile, FileMode.Create)); fileLength = new FileInfo(logFile).Length; } catch (Exception e) { - EventLogger.LogEvent($"Failed to roll size time log: {e.Message}"); + this.EventLogger.LogEvent($"Failed to roll size time log: {e.Message}"); } } @@ -451,28 +467,32 @@ namespace winsw private void ZipFiles(string directory, string fileExtension, string zipFileBaseName) { - if (ZipOlderThanNumDays is null || ZipOlderThanNumDays <= 0) + if (this.ZipOlderThanNumDays is null || this.ZipOlderThanNumDays <= 0) + { return; + } try { foreach (string path in Directory.GetFiles(directory, "*" + fileExtension)) { var fileInfo = new FileInfo(path); - if (fileInfo.LastWriteTimeUtc >= DateTime.UtcNow.AddDays(-ZipOlderThanNumDays.Value)) + if (fileInfo.LastWriteTimeUtc >= DateTime.UtcNow.AddDays(-this.ZipOlderThanNumDays.Value)) + { continue; + } string sourceFileName = Path.GetFileName(path); - string zipFilePattern = fileInfo.LastAccessTimeUtc.ToString(ZipDateFormat); + string zipFilePattern = fileInfo.LastAccessTimeUtc.ToString(this.ZipDateFormat); string zipFilePath = Path.Combine(directory, $"{zipFileBaseName}.{zipFilePattern}.zip"); - ZipOneFile(path, sourceFileName, zipFilePath); + this.ZipOneFile(path, sourceFileName, zipFilePath); File.Delete(path); } } catch (Exception e) { - EventLogger.LogEvent($"Failed to Zip files. Error {e.Message}"); + this.EventLogger.LogEvent($"Failed to Zip files. Error {e.Message}"); } } @@ -490,7 +510,7 @@ namespace winsw } catch (Exception e) { - EventLogger.LogEvent($"Failed to Zip the File {sourceFilePath}. Error {e.Message}"); + this.EventLogger.LogEvent($"Failed to Zip the File {sourceFilePath}. Error {e.Message}"); } finally { @@ -510,7 +530,9 @@ namespace winsw autoRollAtTime.Seconds, 0); if (nowTime > scheduledTime) + { scheduledTime = scheduledTime.AddDays(1); + } double tickTime = (scheduledTime - DateTime.Now).TotalMilliseconds; return tickTime; @@ -519,7 +541,7 @@ namespace winsw private int GetNextFileNumber(string ext, string baseDirectory, string baseFileName, DateTime now) { var nextFileNumber = 0; - var files = Directory.GetFiles(baseDirectory, string.Format("{0}.{1}.#*{2}", baseFileName, now.ToString(FilePattern), ext)); + var files = Directory.GetFiles(baseDirectory, string.Format("{0}.{1}.#*{2}", baseFileName, now.ToString(this.FilePattern), ext)); if (files.Length == 0) { nextFileNumber = 1; @@ -533,11 +555,12 @@ namespace winsw var filenameOnly = Path.GetFileNameWithoutExtension(f); var hashIndex = filenameOnly.IndexOf('#'); var lastNumberAsString = filenameOnly.Substring(hashIndex + 1, 4); - // var lastNumberAsString = filenameOnly.Substring(filenameOnly.Length - 4, 4); if (int.TryParse(lastNumberAsString, out int lastNumber)) { if (lastNumber > nextFileNumber) + { nextFileNumber = lastNumber; + } } else { @@ -551,7 +574,9 @@ namespace winsw } if (nextFileNumber == 0) + { throw new IOException("Cannot roll the file because matching pattern not found"); + } nextFileNumber++; } diff --git a/src/Core/WinSWCore/Logging/IServiceEventLogProvider.cs b/src/Core/WinSWCore/Logging/IServiceEventLogProvider.cs index f35d6e9..0c79fd0 100644 --- a/src/Core/WinSWCore/Logging/IServiceEventLogProvider.cs +++ b/src/Core/WinSWCore/Logging/IServiceEventLogProvider.cs @@ -1,6 +1,6 @@ using System.Diagnostics; -namespace winsw.Logging +namespace WinSW.Logging { /// /// Indicates that the class may reference the event log @@ -11,6 +11,6 @@ namespace winsw.Logging /// Locates Event Log for the service. /// /// Event Log or null if it is not avilable - EventLog? locate(); + EventLog? Locate(); } } diff --git a/src/Core/WinSWCore/Logging/ServiceEventLogAppender.cs b/src/Core/WinSWCore/Logging/ServiceEventLogAppender.cs index 0a62312..34b99ab 100644 --- a/src/Core/WinSWCore/Logging/ServiceEventLogAppender.cs +++ b/src/Core/WinSWCore/Logging/ServiceEventLogAppender.cs @@ -2,7 +2,7 @@ using log4net.Appender; using log4net.Core; -namespace winsw.Logging +namespace WinSW.Logging { /// /// Implementes service Event log appender for log4j. @@ -11,18 +11,18 @@ namespace winsw.Logging public class ServiceEventLogAppender : AppenderSkeleton { #pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. - public IServiceEventLogProvider provider { get; set; } + public IServiceEventLogProvider Provider { get; set; } #pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. - override protected void Append(LoggingEvent loggingEvent) + protected override void Append(LoggingEvent loggingEvent) { - EventLog? eventLog = provider.locate(); + EventLog? eventLog = this.Provider.Locate(); // We write the event iff the provider is ready - eventLog?.WriteEntry(loggingEvent.RenderedMessage, toEventLogEntryType(loggingEvent.Level)); + eventLog?.WriteEntry(loggingEvent.RenderedMessage, ToEventLogEntryType(loggingEvent.Level)); } - private static EventLogEntryType toEventLogEntryType(Level level) + private static EventLogEntryType ToEventLogEntryType(Level level) { if (level.Value >= Level.Error.Value) { diff --git a/src/Core/WinSWCore/Native/ConsoleApis.cs b/src/Core/WinSWCore/Native/ConsoleApis.cs index 9ad144a..0e0e8c5 100644 --- a/src/Core/WinSWCore/Native/ConsoleApis.cs +++ b/src/Core/WinSWCore/Native/ConsoleApis.cs @@ -1,6 +1,8 @@ -using System.Runtime.InteropServices; +#pragma warning disable SA1310 // Field names should not contain underscore -namespace winsw.Native +using System.Runtime.InteropServices; + +namespace WinSW.Native { internal static class ConsoleApis { diff --git a/src/Core/WinSWCore/Native/CredentialApis.cs b/src/Core/WinSWCore/Native/CredentialApis.cs index db02e72..0fb06d3 100644 --- a/src/Core/WinSWCore/Native/CredentialApis.cs +++ b/src/Core/WinSWCore/Native/CredentialApis.cs @@ -1,7 +1,9 @@ -using System; +#pragma warning disable SA1310 // Field names should not contain underscore + +using System; using System.Runtime.InteropServices; -namespace winsw.Native +namespace WinSW.Native { internal static class CredentialApis { diff --git a/src/Core/WinSWCore/Native/Errors.cs b/src/Core/WinSWCore/Native/Errors.cs index 1dce14a..3d9b2c5 100644 --- a/src/Core/WinSWCore/Native/Errors.cs +++ b/src/Core/WinSWCore/Native/Errors.cs @@ -1,4 +1,6 @@ -namespace winsw.Native +#pragma warning disable SA1310 // Field names should not contain underscore + +namespace WinSW.Native { internal static class Errors { diff --git a/src/Core/WinSWCore/Native/HandleApis.cs b/src/Core/WinSWCore/Native/HandleApis.cs index 126c81b..151fb71 100644 --- a/src/Core/WinSWCore/Native/HandleApis.cs +++ b/src/Core/WinSWCore/Native/HandleApis.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace winsw.Native +namespace WinSW.Native { internal static class HandleApis { diff --git a/src/Core/WinSWCore/Native/Libraries.cs b/src/Core/WinSWCore/Native/Libraries.cs index 2b54307..5ca8e5c 100644 --- a/src/Core/WinSWCore/Native/Libraries.cs +++ b/src/Core/WinSWCore/Native/Libraries.cs @@ -1,4 +1,4 @@ -namespace winsw.Native +namespace WinSW.Native { internal static class Libraries { diff --git a/src/Core/WinSWCore/Native/ProcessApis.cs b/src/Core/WinSWCore/Native/ProcessApis.cs index 36241bd..15b5af1 100644 --- a/src/Core/WinSWCore/Native/ProcessApis.cs +++ b/src/Core/WinSWCore/Native/ProcessApis.cs @@ -1,8 +1,10 @@ -using System; +#pragma warning disable SA1310 // Field names should not contain underscore + +using System; using System.Runtime.InteropServices; using System.Security.Principal; -namespace winsw.Native +namespace WinSW.Native { internal static class ProcessApis { @@ -46,12 +48,14 @@ namespace winsw.Native [StructLayout(LayoutKind.Sequential)] internal unsafe struct PROCESS_BASIC_INFORMATION { +#pragma warning disable SA1306 // Field names should begin with lower-case letter private readonly IntPtr Reserved1; private readonly IntPtr PebBaseAddress; private readonly IntPtr Reserved2_1; private readonly IntPtr Reserved2_2; internal readonly IntPtr UniqueProcessId; internal readonly IntPtr InheritedFromUniqueProcessId; +#pragma warning restore SA1306 // Field names should begin with lower-case letter } internal struct PROCESS_INFORMATION diff --git a/src/Core/WinSWCore/Native/Security.cs b/src/Core/WinSWCore/Native/Security.cs index 0d146e0..a151aa6 100644 --- a/src/Core/WinSWCore/Native/Security.cs +++ b/src/Core/WinSWCore/Native/Security.cs @@ -1,9 +1,9 @@ using System; using System.ComponentModel; using System.Runtime.InteropServices; -using static winsw.Native.SecurityApis; +using static WinSW.Native.SecurityApis; -namespace winsw.Native +namespace WinSW.Native { internal static class Security { diff --git a/src/Core/WinSWCore/Native/SecurityApis.cs b/src/Core/WinSWCore/Native/SecurityApis.cs index 4f28ffc..5b1c88b 100644 --- a/src/Core/WinSWCore/Native/SecurityApis.cs +++ b/src/Core/WinSWCore/Native/SecurityApis.cs @@ -1,7 +1,9 @@ -using System; +#pragma warning disable SA1310 // Field names should not contain underscore + +using System; using System.Runtime.InteropServices; -namespace winsw.Native +namespace WinSW.Native { internal static class SecurityApis { diff --git a/src/Core/WinSWCore/Native/Service.cs b/src/Core/WinSWCore/Native/Service.cs index 36e3942..aa2f988 100644 --- a/src/Core/WinSWCore/Native/Service.cs +++ b/src/Core/WinSWCore/Native/Service.cs @@ -3,9 +3,9 @@ using System.ComponentModel; using System.Security.AccessControl; using System.ServiceProcess; using System.Text; -using static winsw.Native.ServiceApis; +using static WinSW.Native.ServiceApis; -namespace winsw.Native +namespace WinSW.Native { public enum SC_ACTION_TYPE { @@ -198,7 +198,8 @@ namespace winsw.Native { fixed (SC_ACTION* actionsPtr = actions) { - if (!ChangeServiceConfig2(this.handle, + if (!ChangeServiceConfig2( + this.handle, ServiceConfigInfoLevels.FAILURE_ACTIONS, new SERVICE_FAILURE_ACTIONS { diff --git a/src/Core/WinSWCore/Native/ServiceApis.cs b/src/Core/WinSWCore/Native/ServiceApis.cs index bd50c1d..d547ad4 100644 --- a/src/Core/WinSWCore/Native/ServiceApis.cs +++ b/src/Core/WinSWCore/Native/ServiceApis.cs @@ -4,7 +4,7 @@ using System.Security.AccessControl; using System.ServiceProcess; using System.Text; -namespace winsw.Native +namespace WinSW.Native { internal static class ServiceApis { diff --git a/src/Core/WinSWCore/Native/Throw.cs b/src/Core/WinSWCore/Native/Throw.cs index 43f3bde..91cd3a4 100644 --- a/src/Core/WinSWCore/Native/Throw.cs +++ b/src/Core/WinSWCore/Native/Throw.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; -namespace winsw.Native +namespace WinSW.Native { internal static class Throw { diff --git a/src/Core/WinSWCore/NullableAttributes.cs b/src/Core/WinSWCore/NullableAttributes.cs index 71aab86..fa9b3ca 100644 --- a/src/Core/WinSWCore/NullableAttributes.cs +++ b/src/Core/WinSWCore/NullableAttributes.cs @@ -3,10 +3,14 @@ namespace System.Diagnostics.CodeAnalysis { /// Specifies that null is allowed as an input even if the corresponding type disallows it. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] - internal sealed class AllowNullAttribute : Attribute { } + internal sealed class AllowNullAttribute : Attribute + { + } /// Specifies that an output may be null even if the corresponding type disallows it. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] - internal sealed class MaybeNullAttribute : Attribute { } + internal sealed class MaybeNullAttribute : Attribute + { + } } #endif diff --git a/src/Core/WinSWCore/PeriodicRollingCalendar.cs b/src/Core/WinSWCore/PeriodicRollingCalendar.cs index 1725153..789c5dc 100644 --- a/src/Core/WinSWCore/PeriodicRollingCalendar.cs +++ b/src/Core/WinSWCore/PeriodicRollingCalendar.cs @@ -1,30 +1,26 @@ using System; -// ReSharper disable InconsistentNaming - -namespace winsw +namespace WinSW { - /** - * This is largely borrowed from the logback Rolling Calendar. - **/ + // This is largely borrowed from the logback Rolling Calendar. public class PeriodicRollingCalendar { - private readonly string _format; - private readonly long _period; - private DateTime _currentRoll; - private DateTime _nextRoll; + private readonly string format; + private readonly long period; + private DateTime currentRoll; + private DateTime nextRoll; public PeriodicRollingCalendar(string format, long period) { - _format = format; - _period = period; - _currentRoll = DateTime.Now; + this.format = format; + this.period = period; + this.currentRoll = DateTime.Now; } - public void init() + public void Init() { - periodicityType = determinePeriodicityType(); - _nextRoll = nextTriggeringTime(_currentRoll, _period); + this.Periodicity = this.DeterminePeriodicityType(); + this.nextRoll = this.NextTriggeringTime(this.currentRoll, this.period); } public enum PeriodicityType @@ -37,23 +33,23 @@ namespace winsw TOP_OF_DAY } - private static readonly PeriodicityType[] VALID_ORDERED_LIST = + private static readonly PeriodicityType[] ValidOrderedList = { PeriodicityType.TOP_OF_MILLISECOND, PeriodicityType.TOP_OF_SECOND, PeriodicityType.TOP_OF_MINUTE, PeriodicityType.TOP_OF_HOUR, PeriodicityType.TOP_OF_DAY }; - private PeriodicityType determinePeriodicityType() + private PeriodicityType DeterminePeriodicityType() { - PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(_format, _period); + PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period); DateTime epoch = new DateTime(1970, 1, 1); - foreach (PeriodicityType i in VALID_ORDERED_LIST) + foreach (PeriodicityType i in ValidOrderedList) { - string r0 = epoch.ToString(_format); - periodicRollingCalendar.periodicityType = i; + string r0 = epoch.ToString(this.format); + periodicRollingCalendar.Periodicity = i; - DateTime next = periodicRollingCalendar.nextTriggeringTime(epoch, 1); - string r1 = next.ToString(_format); + DateTime next = periodicRollingCalendar.NextTriggeringTime(epoch, 1); + string r1 = next.ToString(this.format); if (r0 != r1) { @@ -64,7 +60,7 @@ namespace winsw return PeriodicityType.ERRONEOUS; } - private DateTime nextTriggeringTime(DateTime input, long increment) => periodicityType switch + private DateTime NextTriggeringTime(DateTime input, long increment) => this.Periodicity switch { PeriodicityType.TOP_OF_MILLISECOND => new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond) @@ -86,20 +82,20 @@ namespace winsw new DateTime(input.Year, input.Month, input.Day) .AddDays(increment), - _ => throw new Exception("invalid periodicity type: " + periodicityType), + _ => throw new Exception("invalid periodicity type: " + this.Periodicity), }; - public PeriodicityType periodicityType { get; set; } + public PeriodicityType Periodicity { get; set; } - public bool shouldRoll + public bool ShouldRoll { get { DateTime now = DateTime.Now; - if (now > _nextRoll) + if (now > this.nextRoll) { - _currentRoll = now; - _nextRoll = nextTriggeringTime(now, _period); + this.currentRoll = now; + this.nextRoll = this.NextTriggeringTime(now, this.period); return true; } @@ -107,6 +103,6 @@ namespace winsw } } - public string format => _currentRoll.ToString(_format); + public string Format => this.currentRoll.ToString(this.format); } } diff --git a/src/Core/WinSWCore/ServiceDescriptor.cs b/src/Core/WinSWCore/ServiceDescriptor.cs index ba536cb..a81c1c8 100755 --- a/src/Core/WinSWCore/ServiceDescriptor.cs +++ b/src/Core/WinSWCore/ServiceDescriptor.cs @@ -5,18 +5,17 @@ using System.IO; using System.ServiceProcess; using System.Text; using System.Xml; -using winsw.Configuration; -using winsw.Native; -using winsw.Util; +using WinSW.Configuration; +using WinSW.Native; +using WinSW.Util; -namespace winsw +namespace WinSW { /// /// In-memory representation of the configuration file. /// public class ServiceDescriptor : IWinSWConfiguration { - // ReSharper disable once InconsistentNaming protected readonly XmlDocument dom = new XmlDocument(); private readonly Dictionary environmentVariables; @@ -45,29 +44,35 @@ namespace winsw // find co-located configuration xml. We search up to the ancestor directories to simplify debugging, // as well as trimming off ".vshost" suffix (which is used during debugging) // Get the first parent to go into the recursive loop - string p = ExecutablePath; + string p = this.ExecutablePath; string baseName = Path.GetFileNameWithoutExtension(p); if (baseName.EndsWith(".vshost")) + { baseName = baseName.Substring(0, baseName.Length - 7); + } DirectoryInfo d = new DirectoryInfo(Path.GetDirectoryName(p)); while (true) { if (File.Exists(Path.Combine(d.FullName, baseName + ".xml"))) + { break; + } if (d.Parent is null) + { throw new FileNotFoundException("Unable to locate " + baseName + ".xml file within executable directory or any parents"); + } d = d.Parent; } - BaseName = baseName; - BasePath = Path.Combine(d.FullName, BaseName); + this.BaseName = baseName; + this.BasePath = Path.Combine(d.FullName, this.BaseName); try { - dom.Load(BasePath + ".xml"); + this.dom.Load(this.BasePath + ".xml"); } catch (XmlException e) { @@ -78,13 +83,13 @@ namespace winsw Environment.SetEnvironmentVariable("BASE", d.FullName); // ditto for ID - Environment.SetEnvironmentVariable("SERVICE_ID", Id); + Environment.SetEnvironmentVariable("SERVICE_ID", this.Id); // New name - Environment.SetEnvironmentVariable(WinSWSystem.ENVVAR_NAME_EXECUTABLE_PATH, ExecutablePath); + Environment.SetEnvironmentVariable(WinSWSystem.EnvVarNameExecutablePath, this.ExecutablePath); // Also inject system environment variables - Environment.SetEnvironmentVariable(WinSWSystem.ENVVAR_NAME_SERVICE_ID, Id); + Environment.SetEnvironmentVariable(WinSWSystem.EnvVarNameServiceId, this.Id); this.environmentVariables = this.LoadEnvironmentVariables(); } @@ -101,8 +106,7 @@ namespace winsw this.environmentVariables = this.LoadEnvironmentVariables(); } - // ReSharper disable once InconsistentNaming - public static ServiceDescriptor FromXML(string xml) + public static ServiceDescriptor FromXml(string xml) { var dom = new XmlDocument(); dom.LoadXml(xml); @@ -111,21 +115,23 @@ namespace winsw private string SingleElement(string tagName) { - return SingleElement(tagName, false)!; + return this.SingleElement(tagName, false)!; } private string? SingleElement(string tagName, bool optional) { - XmlNode? n = dom.SelectSingleNode("//" + tagName); + XmlNode? n = this.dom.SelectSingleNode("//" + tagName); if (n is null && !optional) + { throw new InvalidDataException("<" + tagName + "> is missing in configuration XML"); + } return n is null ? null : Environment.ExpandEnvironmentVariables(n.InnerText); } private bool SingleBoolElement(string tagName, bool defaultValue) { - XmlNode? e = dom.SelectSingleNode("//" + tagName); + XmlNode? e = this.dom.SelectSingleNode("//" + tagName); return e is null ? defaultValue : bool.Parse(e.InnerText); } @@ -139,8 +145,8 @@ namespace winsw private TimeSpan SingleTimeSpanElement(XmlNode parent, string tagName, TimeSpan defaultValue) { - string? value = SingleElement(tagName, true); - return value is null ? defaultValue : ParseTimeSpan(value); + string? value = this.SingleElement(tagName, true); + return value is null ? defaultValue : this.ParseTimeSpan(value); } private TimeSpan ParseTimeSpan(string v) @@ -175,14 +181,14 @@ namespace winsw /// /// Path to the executable. /// - public string Executable => SingleElement("executable"); + public string Executable => this.SingleElement("executable"); - public bool HideWindow => SingleBoolElement("hidewindow", Defaults.HideWindow); + public bool HideWindow => this.SingleBoolElement("hidewindow", Defaults.HideWindow); /// /// Optionally specify a different Path to an executable to shutdown the service. /// - public string? StopExecutable => SingleElement("stopexecutable", true); + public string? StopExecutable => this.SingleElement("stopexecutable", true); /// /// arguments or multiple optional argument elements which overrule the arguments element. @@ -191,14 +197,14 @@ namespace winsw { get { - string? arguments = AppendTags("argument", null); + string? arguments = this.AppendTags("argument", null); if (!(arguments is null)) { return arguments; } - XmlNode? argumentsNode = dom.SelectSingleNode("//arguments"); + XmlNode? argumentsNode = this.dom.SelectSingleNode("//arguments"); return argumentsNode is null ? Defaults.Arguments : Environment.ExpandEnvironmentVariables(argumentsNode.InnerText); } @@ -211,14 +217,14 @@ namespace winsw { get { - string? startArguments = AppendTags("startargument", null); + string? startArguments = this.AppendTags("startargument", null); if (!(startArguments is null)) { return startArguments; } - XmlNode? startArgumentsNode = dom.SelectSingleNode("//startarguments"); + XmlNode? startArgumentsNode = this.dom.SelectSingleNode("//startarguments"); return startArgumentsNode is null ? null : Environment.ExpandEnvironmentVariables(startArgumentsNode.InnerText); } @@ -231,14 +237,14 @@ namespace winsw { get { - string? stopArguments = AppendTags("stopargument", null); + string? stopArguments = this.AppendTags("stopargument", null); if (!(stopArguments is null)) { return stopArguments; } - XmlNode? stopArgumentsNode = dom.SelectSingleNode("//stoparguments"); + XmlNode? stopArgumentsNode = this.dom.SelectSingleNode("//stoparguments"); return stopArgumentsNode is null ? null : Environment.ExpandEnvironmentVariables(stopArgumentsNode.InnerText); } @@ -248,7 +254,7 @@ namespace winsw { get { - var wd = SingleElement("workingdirectory", true); + var wd = this.SingleElement("workingdirectory", true); return string.IsNullOrEmpty(wd) ? Defaults.WorkingDirectory : wd!; } } @@ -257,7 +263,7 @@ namespace winsw { get { - XmlNode? argumentNode = ExtensionsConfiguration; + XmlNode? argumentNode = this.ExtensionsConfiguration; XmlNodeList? extensions = argumentNode?.SelectNodes("extension"); if (extensions is null) { @@ -274,7 +280,7 @@ namespace winsw } } - public XmlNode? ExtensionsConfiguration => dom.SelectSingleNode("//extensions"); + public XmlNode? ExtensionsConfiguration => this.dom.SelectSingleNode("//extensions"); /// /// Combines the contents of all the elements of the given name, @@ -282,7 +288,7 @@ namespace winsw /// private string? AppendTags(string tagName, string? defaultValue = null) { - XmlNode? argumentNode = dom.SelectSingleNode("//" + tagName); + XmlNode? argumentNode = this.dom.SelectSingleNode("//" + tagName); if (argumentNode is null) { return defaultValue; @@ -290,7 +296,7 @@ namespace winsw StringBuilder arguments = new StringBuilder(); - XmlNodeList argumentNodeList = dom.SelectNodes("//" + tagName); + XmlNodeList argumentNodeList = this.dom.SelectNodes("//" + tagName); for (int i = 0; i < argumentNodeList.Count; i++) { arguments.Append(' '); @@ -325,7 +331,7 @@ namespace winsw { get { - XmlNode? loggingNode = dom.SelectSingleNode("//logpath"); + XmlNode? loggingNode = this.dom.SelectSingleNode("//logpath"); return loggingNode is null ? Defaults.LogDirectory @@ -340,7 +346,7 @@ namespace winsw string? mode = null; // first, backward compatibility with older configuration - XmlElement? e = (XmlElement?)dom.SelectSingleNode("//logmode"); + XmlElement? e = (XmlElement?)this.dom.SelectSingleNode("//logmode"); if (e != null) { mode = e.InnerText; @@ -348,9 +354,11 @@ namespace winsw else { // this is more modern way, to support nested elements as configuration - e = (XmlElement?)dom.SelectSingleNode("//log"); + e = (XmlElement?)this.dom.SelectSingleNode("//log"); if (e != null) + { mode = e.GetAttribute("mode"); + } } return mode ?? Defaults.LogMode; @@ -361,21 +369,21 @@ namespace winsw { get { - XmlNode? loggingName = dom.SelectSingleNode("//logname"); + XmlNode? loggingName = this.dom.SelectSingleNode("//logname"); - return loggingName is null ? BaseName : Environment.ExpandEnvironmentVariables(loggingName.InnerText); + return loggingName is null ? this.BaseName : Environment.ExpandEnvironmentVariables(loggingName.InnerText); } } - public bool OutFileDisabled => SingleBoolElement("outfiledisabled", Defaults.OutFileDisabled); + public bool OutFileDisabled => this.SingleBoolElement("outfiledisabled", Defaults.OutFileDisabled); - public bool ErrFileDisabled => SingleBoolElement("errfiledisabled", Defaults.ErrFileDisabled); + public bool ErrFileDisabled => this.SingleBoolElement("errfiledisabled", Defaults.ErrFileDisabled); public string OutFilePattern { get { - XmlNode? loggingName = dom.SelectSingleNode("//outfilepattern"); + XmlNode? loggingName = this.dom.SelectSingleNode("//outfilepattern"); return loggingName is null ? Defaults.OutFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText); } @@ -385,7 +393,7 @@ namespace winsw { get { - XmlNode? loggingName = dom.SelectSingleNode("//errfilepattern"); + XmlNode? loggingName = this.dom.SelectSingleNode("//errfilepattern"); return loggingName is null ? Defaults.ErrFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText); } @@ -395,25 +403,25 @@ namespace winsw { get { - XmlElement? e = (XmlElement?)dom.SelectSingleNode("//logmode"); + XmlElement? e = (XmlElement?)this.dom.SelectSingleNode("//logmode"); // this is more modern way, to support nested elements as configuration - e ??= (XmlElement?)dom.SelectSingleNode("//log")!; // WARNING: NRE + e ??= (XmlElement?)this.dom.SelectSingleNode("//log")!; // WARNING: NRE int sizeThreshold; - switch (LogMode) + switch (this.LogMode) { case "rotate": - return new SizeBasedRollingLogAppender(LogDirectory, LogName, OutFileDisabled, ErrFileDisabled, OutFilePattern, ErrFilePattern); + return new SizeBasedRollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern); case "none": return new IgnoreLogAppender(); case "reset": - return new ResetLogAppender(LogDirectory, LogName, OutFileDisabled, ErrFileDisabled, OutFilePattern, ErrFilePattern); + return new ResetLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern); case "roll": - return new RollingLogAppender(LogDirectory, LogName, OutFileDisabled, ErrFileDisabled, OutFilePattern, ErrFilePattern); + return new RollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern); case "roll-by-time": XmlNode? patternNode = e.SelectSingleNode("pattern"); @@ -423,19 +431,19 @@ namespace winsw } var pattern = patternNode.InnerText; - int period = SingleIntElement(e, "period", 1); - return new TimeBasedRollingLogAppender(LogDirectory, LogName, OutFileDisabled, ErrFileDisabled, OutFilePattern, ErrFilePattern, pattern, period); + int period = this.SingleIntElement(e, "period", 1); + return new TimeBasedRollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern, pattern, period); case "roll-by-size": - sizeThreshold = SingleIntElement(e, "sizeThreshold", 10 * 1024) * SizeBasedRollingLogAppender.BYTES_PER_KB; - int keepFiles = SingleIntElement(e, "keepFiles", SizeBasedRollingLogAppender.DEFAULT_FILES_TO_KEEP); - return new SizeBasedRollingLogAppender(LogDirectory, LogName, OutFileDisabled, ErrFileDisabled, OutFilePattern, ErrFilePattern, sizeThreshold, keepFiles); + sizeThreshold = this.SingleIntElement(e, "sizeThreshold", 10 * 1024) * SizeBasedRollingLogAppender.BytesPerKB; + int keepFiles = this.SingleIntElement(e, "keepFiles", SizeBasedRollingLogAppender.DefaultFilesToKeep); + return new SizeBasedRollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern, sizeThreshold, keepFiles); case "append": - return new DefaultLogAppender(LogDirectory, LogName, OutFileDisabled, ErrFileDisabled, OutFilePattern, ErrFilePattern); + return new DefaultLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern); case "roll-by-size-time": - sizeThreshold = SingleIntElement(e, "sizeThreshold", 10 * 1024) * RollingSizeTimeLogAppender.BYTES_PER_KB; + sizeThreshold = this.SingleIntElement(e, "sizeThreshold", 10 * 1024) * RollingSizeTimeLogAppender.BytesPerKB; XmlNode? filePatternNode = e.SelectSingleNode("pattern"); if (filePatternNode is null) { @@ -448,7 +456,9 @@ namespace winsw { // validate it if (!TimeSpan.TryParse(autoRollAtTimeNode.InnerText, out TimeSpan autoRollAtTimeValue)) + { throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but autoRollAtTime does not match the TimeSpan format HH:mm:ss found in configuration XML."); + } autoRollAtTime = autoRollAtTimeValue; } @@ -459,7 +469,9 @@ namespace winsw { // validate it if (!int.TryParse(zipolderthannumdaysNode.InnerText, out int zipolderthannumdaysValue)) + { throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but zipOlderThanNumDays does not match the int format found in configuration XML."); + } zipolderthannumdays = zipolderthannumdaysValue; } @@ -467,10 +479,10 @@ namespace winsw XmlNode? zipdateformatNode = e.SelectSingleNode("zipDateFormat"); string zipdateformat = zipdateformatNode is null ? "yyyyMM" : zipdateformatNode.InnerText; - return new RollingSizeTimeLogAppender(LogDirectory, LogName, OutFileDisabled, ErrFileDisabled, OutFilePattern, ErrFilePattern, sizeThreshold, filePatternNode.InnerText, autoRollAtTime, zipolderthannumdays, zipdateformat); + return new RollingSizeTimeLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern, sizeThreshold, filePatternNode.InnerText, autoRollAtTime, zipolderthannumdays, zipdateformat); default: - throw new InvalidDataException("Undefined logging mode: " + LogMode); + throw new InvalidDataException("Undefined logging mode: " + this.LogMode); } } } @@ -482,7 +494,7 @@ namespace winsw { get { - XmlNodeList? nodeList = dom.SelectNodes("//depend"); + XmlNodeList? nodeList = this.dom.SelectNodes("//depend"); if (nodeList is null) { return Defaults.ServiceDependencies; @@ -498,11 +510,11 @@ namespace winsw } } - public string Id => SingleElement("id"); + public string Id => this.SingleElement("id"); - public string Caption => SingleElement("name"); + public string Caption => this.SingleElement("name"); - public string Description => SingleElement("description"); + public string Description => this.SingleElement("description"); /// /// Start mode of the Service @@ -511,9 +523,11 @@ namespace winsw { get { - string? p = SingleElement("startmode", true); + string? p = this.SingleElement("startmode", true); if (p is null) + { return Defaults.StartMode; + } try { @@ -536,32 +550,32 @@ 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 => dom.SelectSingleNode("//delayedAutoStart") != null; + public bool DelayedAutoStart => this.dom.SelectSingleNode("//delayedAutoStart") != null; /// /// 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 => dom.SelectSingleNode("//beeponshutdown") != null; + public bool BeepOnShutdown => this.dom.SelectSingleNode("//beeponshutdown") != null; /// /// The estimated time required for a pending stop operation (default 15 secs). /// Before the specified amount of time has elapsed, the service should make its next call to the SetServiceStatus function /// with either an incremented checkPoint value or a change in currentState. (see http://msdn.microsoft.com/en-us/library/ms685996.aspx) /// - public TimeSpan WaitHint => SingleTimeSpanElement(dom, "waithint", Defaults.WaitHint); + public TimeSpan WaitHint => this.SingleTimeSpanElement(this.dom, "waithint", Defaults.WaitHint); /// /// The time before the service should make its next call to the SetServiceStatus function /// with an incremented checkPoint value (default 1 sec). /// Do not wait longer than the wait hint. A good interval is one-tenth of the wait hint but not less than 1 second and not more than 10 seconds. /// - public TimeSpan SleepTime => SingleTimeSpanElement(dom, "sleeptime", Defaults.SleepTime); + public TimeSpan SleepTime => this.SingleTimeSpanElement(this.dom, "sleeptime", Defaults.SleepTime); /// /// True if the service can interact with the desktop. /// - public bool Interactive => dom.SelectSingleNode("//interactive") != null; + public bool Interactive => this.dom.SelectSingleNode("//interactive") != null; /// /// Environment variable overrides @@ -576,7 +590,7 @@ namespace winsw { get { - XmlNodeList? nodeList = dom.SelectNodes("//download"); + XmlNodeList? nodeList = this.dom.SelectNodes("//download"); if (nodeList is null) { return Defaults.Downloads; @@ -599,7 +613,7 @@ namespace winsw { get { - XmlNodeList? childNodes = dom.SelectNodes("//onfailure"); + XmlNodeList? childNodes = this.dom.SelectNodes("//onfailure"); if (childNodes is null) { return new SC_ACTION[0]; @@ -618,18 +632,18 @@ namespace winsw _ => throw new Exception("Invalid failure action: " + action) }; XmlAttribute? delay = node.Attributes["delay"]; - result[i] = new SC_ACTION(type, delay != null ? ParseTimeSpan(delay.Value) : TimeSpan.Zero); + result[i] = new SC_ACTION(type, delay != null ? this.ParseTimeSpan(delay.Value) : TimeSpan.Zero); } return result; } } - public TimeSpan ResetFailureAfter => SingleTimeSpanElement(dom, "resetfailure", Defaults.ResetFailureAfter); + public TimeSpan ResetFailureAfter => this.SingleTimeSpanElement(this.dom, "resetfailure", Defaults.ResetFailureAfter); protected string? GetServiceAccountPart(string subNodeName) { - XmlNode? node = dom.SelectSingleNode("//serviceaccount"); + XmlNode? node = this.dom.SelectSingleNode("//serviceaccount"); if (node != null) { @@ -643,13 +657,13 @@ namespace winsw return null; } - public string? ServiceAccountPrompt => GetServiceAccountPart("prompt")?.ToLowerInvariant(); + public string? ServiceAccountPrompt => this.GetServiceAccountPart("prompt")?.ToLowerInvariant(); - protected string? AllowServiceLogon => GetServiceAccountPart("allowservicelogon"); + protected string? AllowServiceLogon => this.GetServiceAccountPart("allowservicelogon"); - public string? ServiceAccountPassword => GetServiceAccountPart("password"); + public string? ServiceAccountPassword => this.GetServiceAccountPart("password"); - public string? ServiceAccountUserName => GetServiceAccountPart("username"); + public string? ServiceAccountUserName => this.GetServiceAccountPart("username"); public bool HasServiceAccount() { @@ -660,9 +674,9 @@ namespace winsw { get { - if (AllowServiceLogon != null) + if (this.AllowServiceLogon != null) { - if (bool.TryParse(AllowServiceLogon, out bool parsedvalue)) + if (bool.TryParse(this.AllowServiceLogon, out bool parsedvalue)) { return parsedvalue; } @@ -675,7 +689,7 @@ namespace winsw /// /// Time to wait for the service to gracefully shutdown the executable before we forcibly kill it /// - public TimeSpan StopTimeout => SingleTimeSpanElement(dom, "stoptimeout", Defaults.StopTimeout); + public TimeSpan StopTimeout => this.SingleTimeSpanElement(this.dom, "stoptimeout", Defaults.StopTimeout); /// /// Desired process priority or null if not specified. @@ -684,19 +698,21 @@ namespace winsw { get { - string? p = SingleElement("priority", true); + string? p = this.SingleElement("priority", true); if (p is null) + { return Defaults.Priority; + } return (ProcessPriorityClass)Enum.Parse(typeof(ProcessPriorityClass), p, true); } } - public string? SecurityDescriptor => SingleElement("securityDescriptor", true); + public string? SecurityDescriptor => this.SingleElement("securityDescriptor", true); private Dictionary LoadEnvironmentVariables() { - XmlNodeList nodeList = dom.SelectNodes("//env"); + XmlNodeList nodeList = this.dom.SelectNodes("//env"); Dictionary environment = new Dictionary(nodeList.Count); for (int i = 0; i < nodeList.Count; i++) { diff --git a/src/Core/WinSWCore/Util/FileHelper.cs b/src/Core/WinSWCore/Util/FileHelper.cs index 23efdec..ecc4f3c 100644 --- a/src/Core/WinSWCore/Util/FileHelper.cs +++ b/src/Core/WinSWCore/Util/FileHelper.cs @@ -6,7 +6,7 @@ using System.IO; using System.Runtime.InteropServices; #endif -namespace winsw.Util +namespace WinSW.Util { public static class FileHelper { diff --git a/src/Core/WinSWCore/Util/ProcessHelper.cs b/src/Core/WinSWCore/Util/ProcessHelper.cs index 644404c..a441a04 100644 --- a/src/Core/WinSWCore/Util/ProcessHelper.cs +++ b/src/Core/WinSWCore/Util/ProcessHelper.cs @@ -4,9 +4,9 @@ using System.ComponentModel; using System.Diagnostics; using System.Threading; using log4net; -using static winsw.Native.ProcessApis; +using static WinSW.Native.ProcessApis; -namespace winsw.Util +namespace WinSW.Util { /// /// Provides helper classes for Process Management @@ -73,8 +73,6 @@ namespace winsw.Util /// Stops the process. /// If the process cannot be stopped within the stop timeout, it gets killed /// - /// PID of the process - /// Stop timeout public static void StopProcess(Process process, TimeSpan stopTimeout) { Logger.Info("Stopping process " + process.Id); @@ -97,6 +95,7 @@ namespace winsw.Util { Logger.Warn("Process " + process.Id + " did not respond to Ctrl+C signal - Killing as fallback"); } + process.Kill(); } catch (Exception ex) @@ -118,8 +117,6 @@ namespace winsw.Util /// Terminate process and its children. /// By default the child processes get terminated first. /// - /// Process PID - /// Stop timeout (for each process) public static void StopProcessTree(Process process, TimeSpan stopTimeout) { StopProcess(process, stopTimeout); @@ -135,14 +132,14 @@ namespace winsw.Util /// Once the process exits, the callback will be invoked. /// /// Process object to be used - /// Arguments to be passed /// Executable, which should be invoked + /// Arguments to be passed /// Additional environment variables /// Working directory /// Priority /// Completion callback. If null, the completion won't be monitored - /// Log handler. If enabled, logs will be redirected to the process and then reported /// Redirect standard input + /// Log handler. If enabled, logs will be redirected to the process and then reported public static void StartProcessAndCallbackForExit( Process processToStart, string? executable = null, @@ -191,7 +188,7 @@ namespace winsw.Util if (logHandler != null) { Logger.Debug("Forwarding logs of the process " + processToStart + " to " + logHandler); - logHandler.log(processToStart.StandardOutput, processToStart.StandardError); + logHandler.Log(processToStart.StandardOutput, processToStart.StandardError); } // monitor the completion of the process diff --git a/src/Core/WinSWCore/Util/SignalHelper.cs b/src/Core/WinSWCore/Util/SignalHelper.cs index cffc249..7be1bfb 100644 --- a/src/Core/WinSWCore/Util/SignalHelper.cs +++ b/src/Core/WinSWCore/Util/SignalHelper.cs @@ -4,9 +4,9 @@ using System.ComponentModel; using System.Diagnostics; using System.Runtime.InteropServices; using log4net; -using winsw.Native; +using WinSW.Native; -namespace winsw.Util +namespace WinSW.Util { internal static class SignalHelper { diff --git a/src/Core/WinSWCore/Util/XmlHelper.cs b/src/Core/WinSWCore/Util/XmlHelper.cs index e593a36..52a38bf 100644 --- a/src/Core/WinSWCore/Util/XmlHelper.cs +++ b/src/Core/WinSWCore/Util/XmlHelper.cs @@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Xml; -namespace winsw.Util +namespace WinSW.Util { public class XmlHelper { @@ -19,7 +19,9 @@ namespace winsw.Util { XmlNode? n = node.SelectSingleNode(tagName); if (n is null && !optional) + { throw new InvalidDataException("<" + tagName + "> is missing in configuration XML"); + } return n is null ? null : Environment.ExpandEnvironmentVariables(n.InnerText); } @@ -36,7 +38,9 @@ namespace winsw.Util { XmlNode? n = node.SelectSingleNode(tagName); if (n is null && !optional) + { throw new InvalidDataException("<" + tagName + "> is missing in configuration XML"); + } return n; } @@ -69,7 +73,9 @@ namespace winsw.Util public static TAttributeType SingleAttribute(XmlElement node, string attributeName, [AllowNull] TAttributeType defaultValue) { if (!node.HasAttribute(attributeName)) + { return defaultValue; + } string rawValue = node.GetAttribute(attributeName); string substitutedValue = Environment.ExpandEnvironmentVariables(rawValue); @@ -90,7 +96,9 @@ namespace winsw.Util where TAttributeType : struct { if (!node.HasAttribute(attributeName)) + { return defaultValue; + } string rawValue = node.GetAttribute(attributeName); string substitutedValue = Environment.ExpandEnvironmentVariables(rawValue); @@ -100,7 +108,8 @@ namespace winsw.Util } catch (ArgumentException ex) { - throw new InvalidDataException("Cannot parse <" + attributeName + "> Enum value from string '" + substitutedValue + + throw new InvalidDataException( + "Cannot parse <" + attributeName + "> Enum value from string '" + substitutedValue + "'. Enum type: " + typeof(TAttributeType), ex); } } diff --git a/src/Core/WinSWCore/WinSWCore.csproj b/src/Core/WinSWCore/WinSWCore.csproj index 68c25e3..9d2349e 100644 --- a/src/Core/WinSWCore/WinSWCore.csproj +++ b/src/Core/WinSWCore/WinSWCore.csproj @@ -11,6 +11,10 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/src/Core/WinSWCore/WinSWException.cs b/src/Core/WinSWCore/WinSWException.cs index 6fed7b7..86bf04b 100644 --- a/src/Core/WinSWCore/WinSWException.cs +++ b/src/Core/WinSWCore/WinSWException.cs @@ -1,15 +1,17 @@ using System; -namespace winsw +namespace WinSW { public class WinSWException : Exception { public WinSWException(string message) : base(message) - { } + { + } public WinSWException(string message, Exception innerException) : base(message, innerException) - { } + { + } } } diff --git a/src/Core/WinSWCore/WinSWSystem.cs b/src/Core/WinSWCore/WinSWSystem.cs index b1739db..bc3190f 100644 --- a/src/Core/WinSWCore/WinSWSystem.cs +++ b/src/Core/WinSWCore/WinSWSystem.cs @@ -1,4 +1,4 @@ -namespace winsw +namespace WinSW { /// /// Class, which contains generic information about WinSW runtime. @@ -9,17 +9,17 @@ /// /// Prefix for all environment variables being injected for WinSW /// - public static readonly string SYSTEM_EVNVVAR_PREFIX = "WINSW_"; + public static readonly string SystemEnvVarPrefix = "WINSW_"; /// /// Variable, which points to the service ID. /// It may be used to determine runaway processes. /// - public static string ENVVAR_NAME_SERVICE_ID => SYSTEM_EVNVVAR_PREFIX + "SERVICE_ID"; + public static string EnvVarNameServiceId => SystemEnvVarPrefix + "SERVICE_ID"; /// /// Variable, which specifies path to the executable being launched by WinSW. /// - public static string ENVVAR_NAME_EXECUTABLE_PATH => SYSTEM_EVNVVAR_PREFIX + "EXECUTABLE"; + public static string EnvVarNameExecutablePath => SystemEnvVarPrefix + "EXECUTABLE"; } } diff --git a/src/Plugins/RunawayProcessKiller/NativeMethods.cs b/src/Plugins/RunawayProcessKiller/NativeMethods.cs index 3b92382..60c5db2 100644 --- a/src/Plugins/RunawayProcessKiller/NativeMethods.cs +++ b/src/Plugins/RunawayProcessKiller/NativeMethods.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace winsw.Plugins.RunawayProcessKiller +namespace WinSW.Plugins.RunawayProcessKiller { public partial class RunawayProcessKillerExtension { diff --git a/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs b/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs index 415f323..9f7cc0a 100644 --- a/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs +++ b/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs @@ -1,15 +1,14 @@ using System; -using System.Collections.Specialized; using System.Diagnostics; using System.IO; using System.Text; using System.Xml; using log4net; -using winsw.Extensions; -using winsw.Util; -using static winsw.Plugins.RunawayProcessKiller.RunawayProcessKillerExtension.NativeMethods; +using WinSW.Extensions; +using WinSW.Util; +using static WinSW.Plugins.RunawayProcessKiller.RunawayProcessKillerExtension.NativeMethods; -namespace winsw.Plugins.RunawayProcessKiller +namespace WinSW.Plugins.RunawayProcessKiller { public partial class RunawayProcessKillerExtension : AbstractWinSWExtension { @@ -177,12 +176,13 @@ namespace winsw.Plugins.RunawayProcessKiller { // We expect the upper logic to process any errors // TODO: a better parser API for types would be useful - Pidfile = XmlHelper.SingleElement(node, "pidfile", false)!; - StopTimeout = TimeSpan.FromMilliseconds(int.Parse(XmlHelper.SingleElement(node, "stopTimeout", false)!)); - ServiceId = descriptor.Id; + this.Pidfile = XmlHelper.SingleElement(node, "pidfile", false)!; + this.StopTimeout = TimeSpan.FromMilliseconds(int.Parse(XmlHelper.SingleElement(node, "stopTimeout", false)!)); + this.ServiceId = descriptor.Id; + // TODO: Consider making it documented var checkWinSWEnvironmentVariable = XmlHelper.SingleElement(node, "checkWinSWEnvironmentVariable", true); - CheckWinSWEnvironmentVariable = checkWinSWEnvironmentVariable is null ? true : bool.Parse(checkWinSWEnvironmentVariable); + this.CheckWinSWEnvironmentVariable = checkWinSWEnvironmentVariable is null ? true : bool.Parse(checkWinSWEnvironmentVariable); } /// @@ -193,16 +193,16 @@ namespace winsw.Plugins.RunawayProcessKiller { // Read PID file from the disk int pid; - if (File.Exists(Pidfile)) + if (File.Exists(this.Pidfile)) { string pidstring; try { - pidstring = File.ReadAllText(Pidfile); + pidstring = File.ReadAllText(this.Pidfile); } catch (Exception ex) { - Logger.Error("Cannot read PID file from " + Pidfile, ex); + Logger.Error("Cannot read PID file from " + this.Pidfile, ex); return; } @@ -212,13 +212,13 @@ namespace winsw.Plugins.RunawayProcessKiller } catch (FormatException e) { - Logger.Error("Invalid PID file number in '" + Pidfile + "'. The runaway process won't be checked", e); + Logger.Error("Invalid PID file number in '" + this.Pidfile + "'. The runaway process won't be checked", e); return; } } else { - Logger.Warn("The requested PID file '" + Pidfile + "' does not exist. The runaway process won't be checked"); + Logger.Warn("The requested PID file '" + this.Pidfile + "' does not exist. The runaway process won't be checked"); return; } @@ -236,9 +236,9 @@ namespace winsw.Plugins.RunawayProcessKiller } // Ensure the process references the service - string expectedEnvVarName = WinSWSystem.ENVVAR_NAME_SERVICE_ID; + string expectedEnvVarName = WinSWSystem.EnvVarNameServiceId; string? affiliatedServiceId = ReadEnvironmentVariable(proc.Handle, expectedEnvVarName); - if (affiliatedServiceId is null && CheckWinSWEnvironmentVariable) + if (affiliatedServiceId is null && this.CheckWinSWEnvironmentVariable) { Logger.Warn("The process " + pid + " has no " + expectedEnvVarName + " environment variable defined. " + "The process has not been started by WinSW, hence it won't be terminated."); @@ -247,10 +247,10 @@ namespace winsw.Plugins.RunawayProcessKiller } // Check the service ID value - if (CheckWinSWEnvironmentVariable && !ServiceId.Equals(affiliatedServiceId)) + if (this.CheckWinSWEnvironmentVariable && !this.ServiceId.Equals(affiliatedServiceId)) { Logger.Warn("The process " + pid + " has been started by Windows service with ID='" + affiliatedServiceId + "'. " - + "It is another service (current service id is '" + ServiceId + "'), hence the process won't be terminated."); + + "It is another service (current service id is '" + this.ServiceId + "'), hence the process won't be terminated."); return; } @@ -258,7 +258,7 @@ namespace winsw.Plugins.RunawayProcessKiller StringBuilder bldr = new StringBuilder("Stopping the runaway process (pid="); bldr.Append(pid); bldr.Append(") and its children. Environment was "); - if (!CheckWinSWEnvironmentVariable) + if (!this.CheckWinSWEnvironmentVariable) { bldr.Append("not "); } @@ -275,17 +275,16 @@ namespace winsw.Plugins.RunawayProcessKiller /// /// Records the started process PID for the future use in OnStart() after the restart. /// - /// public override void OnProcessStarted(Process process) { - Logger.Info("Recording PID of the started process:" + process.Id + ". PID file destination is " + Pidfile); + Logger.Info("Recording PID of the started process:" + process.Id + ". PID file destination is " + this.Pidfile); try { - File.WriteAllText(Pidfile, process.Id.ToString()); + File.WriteAllText(this.Pidfile, process.Id.ToString()); } catch (Exception ex) { - Logger.Error("Cannot update the PID file " + Pidfile, ex); + Logger.Error("Cannot update the PID file " + this.Pidfile, ex); } } } diff --git a/src/Plugins/SharedDirectoryMapper/NativeMethods.cs b/src/Plugins/SharedDirectoryMapper/NativeMethods.cs index 79b8603..12b9b1c 100644 --- a/src/Plugins/SharedDirectoryMapper/NativeMethods.cs +++ b/src/Plugins/SharedDirectoryMapper/NativeMethods.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace winsw.Plugins.SharedDirectoryMapper +namespace WinSW.Plugins.SharedDirectoryMapper { internal static class NativeMethods { diff --git a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs index a17e878..6b3bf99 100644 --- a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs +++ b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs @@ -2,15 +2,15 @@ using System.ComponentModel; using System.Xml; using log4net; -using winsw.Extensions; -using winsw.Util; -using static winsw.Plugins.SharedDirectoryMapper.NativeMethods; +using WinSW.Extensions; +using WinSW.Util; +using static WinSW.Plugins.SharedDirectoryMapper.NativeMethods; -namespace winsw.Plugins.SharedDirectoryMapper +namespace WinSW.Plugins.SharedDirectoryMapper { public class SharedDirectoryMapper : AbstractWinSWExtension { - private readonly List _entries = new List(); + private readonly List entries = new List(); public override string DisplayName => "Shared Directory Mapper"; @@ -23,7 +23,7 @@ namespace winsw.Plugins.SharedDirectoryMapper public SharedDirectoryMapper(bool enableMapping, string directoryUNC, string driveLabel) { SharedDirectoryMapperConfig config = new SharedDirectoryMapperConfig(enableMapping, driveLabel, directoryUNC); - this._entries.Add(config); + this.entries.Add(config); } public override void Configure(ServiceDescriptor descriptor, XmlNode node) @@ -36,7 +36,7 @@ namespace winsw.Plugins.SharedDirectoryMapper if (mapNodes[i] is XmlElement mapElement) { var config = SharedDirectoryMapperConfig.FromXml(mapElement); - this._entries.Add(config); + this.entries.Add(config); } } } @@ -44,7 +44,7 @@ namespace winsw.Plugins.SharedDirectoryMapper public override void OnWrapperStarted() { - foreach (SharedDirectoryMapperConfig config in this._entries) + foreach (SharedDirectoryMapperConfig config in this.entries) { string label = config.Label; string uncPath = config.UNCPath; @@ -72,7 +72,7 @@ namespace winsw.Plugins.SharedDirectoryMapper public override void BeforeWrapperStopped() { - foreach (SharedDirectoryMapperConfig config in this._entries) + foreach (SharedDirectoryMapperConfig config in this.entries) { string label = config.Label; if (config.EnableMapping) diff --git a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapperConfig.cs b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapperConfig.cs index ec532e1..15e622d 100644 --- a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapperConfig.cs +++ b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapperConfig.cs @@ -1,22 +1,24 @@ using System.Xml; -using winsw.Util; +using WinSW.Util; -namespace winsw.Plugins.SharedDirectoryMapper +namespace WinSW.Plugins.SharedDirectoryMapper { /// /// Stores configuration entries for SharedDirectoryMapper extension. /// public class SharedDirectoryMapperConfig { - public bool EnableMapping { get; set; } - public string Label { get; set; } - public string UNCPath { get; set; } + public bool EnableMapping { get; } + + public string Label { get; } + + public string UNCPath { get; } public SharedDirectoryMapperConfig(bool enableMapping, string label, string uncPath) { - EnableMapping = enableMapping; - Label = label; - UNCPath = uncPath; + this.EnableMapping = enableMapping; + this.Label = label; + this.UNCPath = uncPath; } public static SharedDirectoryMapperConfig FromXml(XmlElement node) diff --git a/src/Test/winswTests/Attributes/ElevatedFactAttribute.cs b/src/Test/winswTests/Attributes/ElevatedFactAttribute.cs index e785dbd..ab4cbe8 100644 --- a/src/Test/winswTests/Attributes/ElevatedFactAttribute.cs +++ b/src/Test/winswTests/Attributes/ElevatedFactAttribute.cs @@ -1,8 +1,7 @@ using System; -using winsw; using Xunit; -namespace winswTests +namespace WinSW.Tests { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] internal sealed class ElevatedFactAttribute : FactAttribute diff --git a/src/Test/winswTests/Configuration/ExamplesTest.cs b/src/Test/winswTests/Configuration/ExamplesTest.cs index bf6d8b9..e76d60a 100644 --- a/src/Test/winswTests/Configuration/ExamplesTest.cs +++ b/src/Test/winswTests/Configuration/ExamplesTest.cs @@ -1,11 +1,10 @@ using System; using System.IO; using System.Xml; -using winsw; -using winswTests.Util; +using WinSW.Tests.Util; using Xunit; -namespace winswTests.Configuration +namespace WinSW.Tests.Configuration { /// /// Tests example configuration files. diff --git a/src/Test/winswTests/DownloadConfigTests.cs b/src/Test/winswTests/DownloadConfigTests.cs index 797235c..910aa31 100644 --- a/src/Test/winswTests/DownloadConfigTests.cs +++ b/src/Test/winswTests/DownloadConfigTests.cs @@ -1,9 +1,8 @@ using System.IO; -using winsw; -using winswTests.Util; +using WinSW.Tests.Util; using Xunit; -namespace winswTests +namespace WinSW.Tests { public class DownloadConfigTests { @@ -15,14 +14,14 @@ namespace winswTests { // Roundtrip data Download d = new Download(From, To); - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithDownload(d) .ToServiceDescriptor(true); - var loaded = GetSingleEntry(sd); + var loaded = this.GetSingleEntry(sd); // Check default values Assert.False(loaded.FailOnError); - Assert.Equal(Download.AuthType.none, loaded.Auth); + Assert.Equal(Download.AuthType.None, loaded.Auth); Assert.Null(loaded.Username); Assert.Null(loaded.Password); Assert.False(loaded.UnsecureAuth); @@ -32,15 +31,15 @@ namespace winswTests public void Roundtrip_BasicAuth() { // Roundtrip data - Download d = new Download(From, To, true, Download.AuthType.basic, "aUser", "aPassword", true); - var sd = ConfigXmlBuilder.create() + Download d = new Download(From, To, true, Download.AuthType.Basic, "aUser", "aPassword", true); + var sd = ConfigXmlBuilder.Create() .WithDownload(d) .ToServiceDescriptor(true); - var loaded = GetSingleEntry(sd); + var loaded = this.GetSingleEntry(sd); // Check default values Assert.True(loaded.FailOnError); - Assert.Equal(Download.AuthType.basic, loaded.Auth); + Assert.Equal(Download.AuthType.Basic, loaded.Auth); Assert.Equal("aUser", loaded.Username); Assert.Equal("aPassword", loaded.Password); Assert.True(loaded.UnsecureAuth); @@ -50,15 +49,15 @@ namespace winswTests public void Roundtrip_SSPI() { // Roundtrip data - Download d = new Download(From, To, false, Download.AuthType.sspi); - var sd = ConfigXmlBuilder.create() + Download d = new Download(From, To, false, Download.AuthType.Sspi); + var sd = ConfigXmlBuilder.Create() .WithDownload(d) .ToServiceDescriptor(true); - var loaded = GetSingleEntry(sd); + var loaded = this.GetSingleEntry(sd); // Check default values Assert.False(loaded.FailOnError); - Assert.Equal(Download.AuthType.sspi, loaded.Auth); + Assert.Equal(Download.AuthType.Sspi, loaded.Auth); Assert.Null(loaded.Username); Assert.Null(loaded.Password); Assert.False(loaded.UnsecureAuth); @@ -72,22 +71,22 @@ namespace winswTests public void RejectBasicAuth_With_UnsecureProtocol(string protocolPrefix) { string unsecureFrom = protocolPrefix + "myServer.com:8080/file.txt"; - var d = new Download(unsecureFrom, To, auth: Download.AuthType.basic, username: "aUser", password: "aPassword"); - AssertInitializationFails(d, "Warning: you're sending your credentials in clear text to the server"); + var d = new Download(unsecureFrom, To, auth: Download.AuthType.Basic, username: "aUser", password: "aPassword"); + this.AssertInitializationFails(d, "Warning: you're sending your credentials in clear text to the server"); } [Fact] public void RejectBasicAuth_Without_Username() { - var d = new Download(From, To, auth: Download.AuthType.basic, username: null, password: "aPassword"); - AssertInitializationFails(d, "Basic Auth is enabled, but username is not specified"); + var d = new Download(From, To, auth: Download.AuthType.Basic, username: null, password: "aPassword"); + this.AssertInitializationFails(d, "Basic Auth is enabled, but username is not specified"); } [Fact] public void RejectBasicAuth_Without_Password() { - var d = new Download(From, To, auth: Download.AuthType.basic, username: "aUser", password: null); - AssertInitializationFails(d, "Basic Auth is enabled, but password is not specified"); + var d = new Download(From, To, auth: Download.AuthType.Basic, username: "aUser", password: null); + this.AssertInitializationFails(d, "Basic Auth is enabled, but password is not specified"); } /// @@ -100,11 +99,11 @@ namespace winswTests { Download d = new Download(From, To, failOnError); - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithDownload(d) .ToServiceDescriptor(true); - var loaded = GetSingleEntry(sd); + var loaded = this.GetSingleEntry(sd); Assert.Equal(From, loaded.From); Assert.Equal(To, loaded.To); Assert.Equal(failOnError, loaded.FailOnError); @@ -116,11 +115,11 @@ namespace winswTests [Fact] public void Download_FailOnError_Undefined() { - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithRawEntry("") .ToServiceDescriptor(true); - var loaded = GetSingleEntry(sd); + var loaded = this.GetSingleEntry(sd); Assert.False(loaded.FailOnError); } @@ -131,22 +130,22 @@ namespace winswTests [InlineData("Sspi")] public void AuthType_Is_CaseInsensitive(string authType) { - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithRawEntry("") .ToServiceDescriptor(true); - var loaded = GetSingleEntry(sd); - Assert.Equal(Download.AuthType.sspi, loaded.Auth); + var loaded = this.GetSingleEntry(sd); + Assert.Equal(Download.AuthType.Sspi, loaded.Auth); } [Fact] public void Should_Fail_On_Unsupported_AuthType() { // TODO: will need refactoring once all fields are being parsed on startup - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithRawEntry("") .ToServiceDescriptor(true); - var e = Assert.Throws(() => GetSingleEntry(sd)); + var e = Assert.Throws(() => this.GetSingleEntry(sd)); Assert.StartsWith("Cannot parse Enum value from string 'digest'", e.Message); } @@ -188,11 +187,11 @@ namespace winswTests private void AssertInitializationFails(Download download, string expectedMessagePart = null) { - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithDownload(download) .ToServiceDescriptor(true); - var e = Assert.Throws(() => GetSingleEntry(sd)); + var e = Assert.Throws(() => this.GetSingleEntry(sd)); Assert.StartsWith(expectedMessagePart, e.Message); } } diff --git a/src/Test/winswTests/DownloadTests.cs b/src/Test/winswTests/DownloadTests.cs index f29abe2..c717c61 100644 --- a/src/Test/winswTests/DownloadTests.cs +++ b/src/Test/winswTests/DownloadTests.cs @@ -4,11 +4,10 @@ using System.Net; using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Threading.Tasks; -using winsw; -using winswTests.Util; +using WinSW.Tests.Util; using Xunit; -namespace winswTests +namespace WinSW.Tests { public class DownloadTests : IDisposable { @@ -107,7 +106,7 @@ namespace winswTests await this.TestClientServerAsync( async (source, dest) => { - await new Download(source, dest, false, Download.AuthType.none).PerformAsync(); + await new Download(source, dest, false, Download.AuthType.None).PerformAsync(); Assert.Equal(this.contents, File.ReadAllBytes(dest)); }, context => @@ -132,7 +131,7 @@ namespace winswTests await this.TestClientServerAsync( async (source, dest) => { - await new Download(source, dest, false, Download.AuthType.basic, username, password, true).PerformAsync(); + await new Download(source, dest, false, Download.AuthType.Basic, username, password, true).PerformAsync(); Assert.Equal(this.contents, File.ReadAllBytes(dest)); }, context => diff --git a/src/Test/winswTests/Extensions/ExtensionTestBase.cs b/src/Test/winswTests/Extensions/ExtensionTestBase.cs index 74f85cc..b6a6365 100644 --- a/src/Test/winswTests/Extensions/ExtensionTestBase.cs +++ b/src/Test/winswTests/Extensions/ExtensionTestBase.cs @@ -1,6 +1,6 @@ using System; -namespace winswTests.Extensions +namespace WinSW.Tests.Extensions { /// /// Base class for testing of WinSW Extensions. diff --git a/src/Test/winswTests/Extensions/RunawayProcessKillerTest.cs b/src/Test/winswTests/Extensions/RunawayProcessKillerTest.cs index 5d9ca0b..f84c032 100644 --- a/src/Test/winswTests/Extensions/RunawayProcessKillerTest.cs +++ b/src/Test/winswTests/Extensions/RunawayProcessKillerTest.cs @@ -1,20 +1,19 @@ using System; using System.Diagnostics; using System.IO; -using winsw; -using winsw.Extensions; -using winsw.Plugins.RunawayProcessKiller; -using winsw.Util; -using winswTests.Util; +using WinSW.Extensions; +using WinSW.Plugins.RunawayProcessKiller; +using WinSW.Tests.Util; +using WinSW.Util; using Xunit; -namespace winswTests.Extensions +namespace WinSW.Tests.Extensions { public class RunawayProcessKillerExtensionTest : ExtensionTestBase { - readonly ServiceDescriptor _testServiceDescriptor; + private readonly ServiceDescriptor testServiceDescriptor; - readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension)); + private readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension)); public RunawayProcessKillerExtensionTest() { @@ -27,19 +26,19 @@ $@" -Xrs -jar \""%BASE%\slave.jar\"" -jnlpUrl ... - + foo/bar/pid.txt 5000 "; - _testServiceDescriptor = ServiceDescriptor.FromXML(seedXml); + this.testServiceDescriptor = ServiceDescriptor.FromXml(seedXml); } [Fact] public void LoadExtensions() { - WinSWExtensionManager manager = new WinSWExtensionManager(_testServiceDescriptor); + WinSWExtensionManager manager = new WinSWExtensionManager(this.testServiceDescriptor); manager.LoadExtensions(); _ = Assert.Single(manager.Extensions); @@ -53,7 +52,7 @@ $@" [Fact] public void StartStopExtension() { - WinSWExtensionManager manager = new WinSWExtensionManager(_testServiceDescriptor); + WinSWExtensionManager manager = new WinSWExtensionManager(this.testServiceDescriptor); manager.LoadExtensions(); manager.FireOnWrapperStarted(); manager.FireBeforeWrapperStopped(); @@ -72,14 +71,14 @@ $@" ps.Arguments = "/c pause"; ps.UseShellExecute = false; ps.RedirectStandardOutput = true; - ps.EnvironmentVariables[WinSWSystem.ENVVAR_NAME_SERVICE_ID] = winswId; + ps.EnvironmentVariables[WinSWSystem.EnvVarNameServiceId] = winswId; proc.Start(); try { // Generate extension and ensure that the roundtrip is correct var pidfile = Path.Combine(tmpDir, "process.pid"); - var sd = ConfigXmlBuilder.create(id: winswId) + var sd = ConfigXmlBuilder.Create(id: winswId) .WithRunawayProcessKiller(new RunawayProcessKillerExtension(pidfile), extensionId) .ToServiceDescriptor(); WinSWExtensionManager manager = new WinSWExtensionManager(sd); diff --git a/src/Test/winswTests/Extensions/SharedDirectoryMapperConfigTest.cs b/src/Test/winswTests/Extensions/SharedDirectoryMapperConfigTest.cs index 7b8cce0..7a87694 100644 --- a/src/Test/winswTests/Extensions/SharedDirectoryMapperConfigTest.cs +++ b/src/Test/winswTests/Extensions/SharedDirectoryMapperConfigTest.cs @@ -1,15 +1,14 @@ -using winsw; -using winsw.Extensions; -using winsw.Plugins.SharedDirectoryMapper; +using WinSW.Extensions; +using WinSW.Plugins.SharedDirectoryMapper; using Xunit; -namespace winswTests.Extensions +namespace WinSW.Tests.Extensions { public class SharedDirectoryMapperConfigTest : ExtensionTestBase { - readonly ServiceDescriptor _testServiceDescriptor; + private readonly ServiceDescriptor testServiceDescriptor; - readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(SharedDirectoryMapper)); + private readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(SharedDirectoryMapper)); public SharedDirectoryMapperConfigTest() { @@ -22,13 +21,13 @@ $@" -Xrs -jar \""%BASE%\slave.jar\"" -jnlpUrl ... - + - + @@ -36,13 +35,13 @@ $@" "; - _testServiceDescriptor = ServiceDescriptor.FromXML(seedXml); + this.testServiceDescriptor = ServiceDescriptor.FromXml(seedXml); } [Fact] public void LoadExtensions() { - WinSWExtensionManager manager = new WinSWExtensionManager(_testServiceDescriptor); + WinSWExtensionManager manager = new WinSWExtensionManager(this.testServiceDescriptor); manager.LoadExtensions(); Assert.Equal(2, manager.Extensions.Count); } @@ -50,7 +49,7 @@ $@" [Fact] public void StartStopExtension() { - WinSWExtensionManager manager = new WinSWExtensionManager(_testServiceDescriptor); + WinSWExtensionManager manager = new WinSWExtensionManager(this.testServiceDescriptor); manager.LoadExtensions(); manager.FireOnWrapperStarted(); manager.FireBeforeWrapperStopped(); diff --git a/src/Test/winswTests/Extensions/SharedDirectoryMapperTests.cs b/src/Test/winswTests/Extensions/SharedDirectoryMapperTests.cs index 98d66b7..9041978 100644 --- a/src/Test/winswTests/Extensions/SharedDirectoryMapperTests.cs +++ b/src/Test/winswTests/Extensions/SharedDirectoryMapperTests.cs @@ -3,10 +3,10 @@ using System; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using winsw.Plugins.SharedDirectoryMapper; +using WinSW.Plugins.SharedDirectoryMapper; using Xunit; -namespace winswTests.Extensions +namespace WinSW.Tests.Extensions { // TODO: Assert.Throws public class SharedDirectoryMapperTests diff --git a/src/Test/winswTests/MainTest.cs b/src/Test/winswTests/MainTest.cs index c17599b..1acc901 100644 --- a/src/Test/winswTests/MainTest.cs +++ b/src/Test/winswTests/MainTest.cs @@ -1,10 +1,9 @@ using System; using System.ServiceProcess; -using winsw; -using winswTests.Util; +using WinSW.Tests.Util; using Xunit; -namespace winswTests +namespace WinSW.Tests { public class MainTest { @@ -47,6 +46,7 @@ namespace winswTests Assert.Contains("start", cliOut); Assert.Contains("help", cliOut); Assert.Contains("version", cliOut); + // TODO: check all commands after the migration of ccommands to enum } diff --git a/src/Test/winswTests/ServiceDescriptorTests.cs b/src/Test/winswTests/ServiceDescriptorTests.cs index 22f7833..240fb0f 100644 --- a/src/Test/winswTests/ServiceDescriptorTests.cs +++ b/src/Test/winswTests/ServiceDescriptorTests.cs @@ -1,22 +1,21 @@ using System; using System.Diagnostics; using System.ServiceProcess; -using winsw; -using winswTests.Util; +using WinSW.Tests.Util; using Xunit; -namespace winswTests +namespace WinSW.Tests { public class ServiceDescriptorTests { - private ServiceDescriptor _extendedServiceDescriptor; - private const string ExpectedWorkingDirectory = @"Z:\Path\SubPath"; private const string Username = "User"; private const string Password = "Password"; private const string Domain = "Domain"; private const string AllowServiceAccountLogonRight = "true"; + private ServiceDescriptor extendedServiceDescriptor; + public ServiceDescriptorTests() { string seedXml = @@ -35,13 +34,13 @@ $@" {ExpectedWorkingDirectory} C:\logs "; - _extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml); + this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml); } [Fact] public void DefaultStartMode() { - Assert.Equal(ServiceStartMode.Automatic, _extendedServiceDescriptor.StartMode); + Assert.Equal(ServiceStartMode.Automatic, this.extendedServiceDescriptor.StartMode); } [Fact] @@ -65,8 +64,8 @@ $@" C:\logs "; - _extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml); - Assert.Throws(() => _extendedServiceDescriptor.StartMode); + this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml); + Assert.Throws(() => this.extendedServiceDescriptor.StartMode); } [Fact] @@ -90,47 +89,47 @@ $@" C:\logs "; - _extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml); - Assert.Equal(ServiceStartMode.Manual, _extendedServiceDescriptor.StartMode); + this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml); + Assert.Equal(ServiceStartMode.Manual, this.extendedServiceDescriptor.StartMode); } [Fact] public void VerifyWorkingDirectory() { - Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory); - Assert.Equal(ExpectedWorkingDirectory, _extendedServiceDescriptor.WorkingDirectory); + Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory); + Assert.Equal(ExpectedWorkingDirectory, this.extendedServiceDescriptor.WorkingDirectory); } [Fact] public void VerifyServiceLogonRight() { - Assert.True(_extendedServiceDescriptor.AllowServiceAcountLogonRight); + Assert.True(this.extendedServiceDescriptor.AllowServiceAcountLogonRight); } [Fact] public void VerifyUsername() { - Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory); - Assert.Equal(Domain + "\\" + Username, _extendedServiceDescriptor.ServiceAccountUserName); + Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory); + Assert.Equal(Domain + "\\" + Username, this.extendedServiceDescriptor.ServiceAccountUserName); } [Fact] public void VerifyPassword() { - Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory); - Assert.Equal(Password, _extendedServiceDescriptor.ServiceAccountPassword); + Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this.extendedServiceDescriptor.WorkingDirectory); + Assert.Equal(Password, this.extendedServiceDescriptor.ServiceAccountPassword); } [Fact] public void Priority() { - var sd = ServiceDescriptor.FromXML("testnormal"); + var sd = ServiceDescriptor.FromXml("testnormal"); Assert.Equal(ProcessPriorityClass.Normal, sd.Priority); - sd = ServiceDescriptor.FromXML("testidle"); + sd = ServiceDescriptor.FromXml("testidle"); Assert.Equal(ProcessPriorityClass.Idle, sd.Priority); - sd = ServiceDescriptor.FromXML("test"); + sd = ServiceDescriptor.FromXml("test"); Assert.Equal(ProcessPriorityClass.Normal, sd.Priority); } @@ -140,7 +139,7 @@ $@" const string seedXml = "" + "60sec" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); Assert.Equal(TimeSpan.FromSeconds(60), serviceDescriptor.StopTimeout); } @@ -151,7 +150,7 @@ $@" const string seedXml = "" + "10min" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); Assert.Equal(TimeSpan.FromMinutes(10), serviceDescriptor.StopTimeout); } @@ -162,7 +161,7 @@ $@" const string seedXml = "" + "MyTestApp" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); Assert.Equal("MyTestApp", serviceDescriptor.LogName); } @@ -173,7 +172,7 @@ $@" const string seedXml = "" + "true" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); Assert.True(serviceDescriptor.OutFileDisabled); } @@ -184,7 +183,7 @@ $@" const string seedXml = "" + "true" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); Assert.True(serviceDescriptor.ErrFileDisabled); } @@ -195,7 +194,7 @@ $@" const string seedXml = "" + ".out.test.log" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); Assert.Equal(".out.test.log", serviceDescriptor.OutFilePattern); } @@ -206,7 +205,7 @@ $@" const string seedXml = "" + ".err.test.log" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); Assert.Equal(".err.test.log", serviceDescriptor.ErrFilePattern); } @@ -222,12 +221,12 @@ $@" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); serviceDescriptor.BaseName = "service"; var logHandler = serviceDescriptor.LogHandler as SizeBasedRollingLogAppender; Assert.NotNull(logHandler); - Assert.Equal(112 * 1024, logHandler.SizeTheshold); + Assert.Equal(112 * 1024, logHandler.SizeThreshold); Assert.Equal(113, logHandler.FilesToKeep); } @@ -242,7 +241,7 @@ $@" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); serviceDescriptor.BaseName = "service"; var logHandler = serviceDescriptor.LogHandler as TimeBasedRollingLogAppender; @@ -263,12 +262,12 @@ $@" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); serviceDescriptor.BaseName = "service"; var logHandler = serviceDescriptor.LogHandler as RollingSizeTimeLogAppender; Assert.NotNull(logHandler); - Assert.Equal(10240 * 1024, logHandler.SizeTheshold); + Assert.Equal(10240 * 1024, logHandler.SizeThreshold); Assert.Equal("yyyy-MM-dd", logHandler.FilePattern); Assert.Equal((TimeSpan?)new TimeSpan(0, 0, 0), logHandler.AutoRollAtTime); } @@ -284,7 +283,7 @@ $@" + "true1" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); Assert.False(serviceDescriptor.AllowServiceAcountLogonRight); } @@ -298,14 +297,14 @@ $@" + "" + Password + "" + "" + ""; - var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); + var serviceDescriptor = ServiceDescriptor.FromXml(seedXml); Assert.False(serviceDescriptor.AllowServiceAcountLogonRight); } [Fact] public void VerifyWaitHint_FullXML() { - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithTag("waithint", "20 min") .ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromMinutes(20), sd.WaitHint); @@ -317,7 +316,7 @@ $@" [Fact] public void VerifyWaitHint_XMLWithoutVersion() { - var sd = ConfigXmlBuilder.create(printXMLVersion: false) + var sd = ConfigXmlBuilder.Create(printXMLVersion: false) .WithTag("waithint", "21 min") .ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromMinutes(21), sd.WaitHint); @@ -326,7 +325,7 @@ $@" [Fact] public void VerifyWaitHint_XMLWithoutComment() { - var sd = ConfigXmlBuilder.create(xmlComment: null) + var sd = ConfigXmlBuilder.Create(xmlComment: null) .WithTag("waithint", "22 min") .ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromMinutes(22), sd.WaitHint); @@ -335,7 +334,7 @@ $@" [Fact] public void VerifyWaitHint_XMLWithoutVersionAndComment() { - var sd = ConfigXmlBuilder.create(xmlComment: null, printXMLVersion: false) + var sd = ConfigXmlBuilder.Create(xmlComment: null, printXMLVersion: false) .WithTag("waithint", "23 min") .ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromMinutes(23), sd.WaitHint); @@ -344,21 +343,21 @@ $@" [Fact] public void VerifySleepTime() { - var sd = ConfigXmlBuilder.create().WithTag("sleeptime", "3 hrs").ToServiceDescriptor(true); + var sd = ConfigXmlBuilder.Create().WithTag("sleeptime", "3 hrs").ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromHours(3), sd.SleepTime); } [Fact] public void VerifyResetFailureAfter() { - var sd = ConfigXmlBuilder.create().WithTag("resetfailure", "75 sec").ToServiceDescriptor(true); + var sd = ConfigXmlBuilder.Create().WithTag("resetfailure", "75 sec").ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromSeconds(75), sd.ResetFailureAfter); } [Fact] public void VerifyStopTimeout() { - var sd = ConfigXmlBuilder.create().WithTag("stoptimeout", "35 secs").ToServiceDescriptor(true); + var sd = ConfigXmlBuilder.Create().WithTag("stoptimeout", "35 secs").ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromSeconds(35), sd.StopTimeout); } @@ -368,14 +367,14 @@ $@" [Fact] public void Arguments_LegacyParam() { - var sd = ConfigXmlBuilder.create().WithTag("arguments", "arg").ToServiceDescriptor(true); + var sd = ConfigXmlBuilder.Create().WithTag("arguments", "arg").ToServiceDescriptor(true); Assert.Equal("arg", sd.Arguments); } [Fact] public void Arguments_NewParam_Single() { - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithTag("argument", "--arg1=2") .ToServiceDescriptor(true); Assert.Equal(" --arg1=2", sd.Arguments); @@ -384,7 +383,7 @@ $@" [Fact] public void Arguments_NewParam_MultipleArgs() { - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithTag("argument", "--arg1=2") .WithTag("argument", "--arg2=123") .WithTag("argument", "--arg3=null") @@ -398,7 +397,7 @@ $@" [Fact] public void Arguments_Bothparam_Priorities() { - var sd = ConfigXmlBuilder.create() + var sd = ConfigXmlBuilder.Create() .WithTag("arguments", "--arg1=2 --arg2=3") .WithTag("argument", "--arg2=123") .WithTag("argument", "--arg3=null") @@ -411,7 +410,7 @@ $@" [InlineData(false)] public void DelayedStart_RoundTrip(bool enabled) { - var bldr = ConfigXmlBuilder.create(); + var bldr = ConfigXmlBuilder.Create(); if (enabled) { bldr = bldr.WithDelayedAutoStart(); diff --git a/src/Test/winswTests/Util/CLITestHelper.cs b/src/Test/winswTests/Util/CLITestHelper.cs index f6437ee..65cc55b 100644 --- a/src/Test/winswTests/Util/CLITestHelper.cs +++ b/src/Test/winswTests/Util/CLITestHelper.cs @@ -1,9 +1,8 @@ using System; using System.IO; -using winsw; using Xunit; -namespace winswTests.Util +namespace WinSW.Tests.Util { /// /// Helper for WinSW CLI testing @@ -25,7 +24,7 @@ $@" C:\winsw\logs "; - public static readonly ServiceDescriptor DefaultServiceDescriptor = ServiceDescriptor.FromXML(SeedXml); + public static readonly ServiceDescriptor DefaultServiceDescriptor = ServiceDescriptor.FromXml(SeedXml); /// /// Runs a simle test, which returns the output CLI @@ -115,13 +114,13 @@ $@" public Exception Exception { get; } - public bool HasException => Exception != null; + public bool HasException => this.Exception != null; public CLITestResult(string output, string error, Exception exception = null) { - Out = output; - Error = error; - Exception = exception; + this.Out = output; + this.Error = error; + this.Exception = exception; } } } diff --git a/src/Test/winswTests/Util/ConfigXmlBuilder.cs b/src/Test/winswTests/Util/ConfigXmlBuilder.cs index 340cd27..6f38519 100644 --- a/src/Test/winswTests/Util/ConfigXmlBuilder.cs +++ b/src/Test/winswTests/Util/ConfigXmlBuilder.cs @@ -1,36 +1,45 @@ using System; using System.Collections.Generic; using System.Text; -using winsw; -using winsw.Plugins.RunawayProcessKiller; -using winswTests.Extensions; +using WinSW.Plugins.RunawayProcessKiller; +using WinSW.Tests.Extensions; -namespace winswTests.Util +namespace WinSW.Tests.Util { /// /// Configuration XML builder, which simplifies testing of WinSW Configuration file. /// - class ConfigXmlBuilder + internal class ConfigXmlBuilder { public string Name { get; set; } + public string Id { get; set; } + public string Description { get; set; } + public string Executable { get; set; } - public bool PrintXMLVersion { get; set; } - public string XMLComment { get; set; } - public List ExtensionXmls { get; private set; } + + public bool PrintXmlVersion { get; set; } + + public string XmlComment { get; set; } + + public List ExtensionXmls { get; } private readonly List configEntries; // TODO: Switch to the initializer? private ConfigXmlBuilder() { - configEntries = new List(); - ExtensionXmls = new List(); + this.configEntries = new List(); + this.ExtensionXmls = new List(); } - public static ConfigXmlBuilder create(string id = null, string name = null, - string description = null, string executable = null, bool printXMLVersion = true, + public static ConfigXmlBuilder Create( + string id = null, + string name = null, + string description = null, + string executable = null, + bool printXMLVersion = true, string xmlComment = "") { var config = new ConfigXmlBuilder(); @@ -38,43 +47,43 @@ namespace winswTests.Util config.Name = name ?? "MyApp Service"; config.Description = description ?? "MyApp Service (powered by WinSW)"; config.Executable = executable ?? "%BASE%\\myExecutable.exe"; - config.PrintXMLVersion = printXMLVersion; - config.XMLComment = (xmlComment != null && xmlComment.Length == 0) + config.PrintXmlVersion = printXMLVersion; + config.XmlComment = (xmlComment != null && xmlComment.Length == 0) ? "Just a sample configuration file generated by the test suite" : xmlComment; return config; } - public string ToXMLString(bool dumpConfig = false) + public string ToXmlString(bool dumpConfig = false) { StringBuilder str = new StringBuilder(); - if (PrintXMLVersion) + if (this.PrintXmlVersion) { // TODO: The encoding is generally wrong str.Append("\n"); } - if (XMLComment != null) + if (this.XmlComment != null) { - str.AppendFormat("\n", XMLComment); + str.AppendFormat("\n", this.XmlComment); } str.Append("\n"); - str.AppendFormat(" {0}\n", Id); - str.AppendFormat(" {0}\n", Name); - str.AppendFormat(" {0}\n", Description); - str.AppendFormat(" {0}\n", Executable); - foreach (string entry in configEntries) + str.AppendFormat(" {0}\n", this.Id); + str.AppendFormat(" {0}\n", this.Name); + str.AppendFormat(" {0}\n", this.Description); + str.AppendFormat(" {0}\n", this.Executable); + foreach (string entry in this.configEntries) { // We do not care much about pretty formatting here str.AppendFormat(" {0}\n", entry); } // Extensions - if (ExtensionXmls.Count > 0) + if (this.ExtensionXmls.Count > 0) { str.Append(" \n"); - foreach (string xml in ExtensionXmls) + foreach (string xml in this.ExtensionXmls) { str.Append(xml); } @@ -95,18 +104,18 @@ namespace winswTests.Util public ServiceDescriptor ToServiceDescriptor(bool dumpConfig = false) { - return ServiceDescriptor.FromXML(ToXMLString(dumpConfig)); + return ServiceDescriptor.FromXml(this.ToXmlString(dumpConfig)); } public ConfigXmlBuilder WithRawEntry(string entry) { - configEntries.Add(entry); + this.configEntries.Add(entry); return this; } public ConfigXmlBuilder WithTag(string tagName, string value) { - return WithRawEntry(string.Format("<{0}>{1}", tagName, value)); + return this.WithRawEntry(string.Format("<{0}>{1}", tagName, value)); } public ConfigXmlBuilder WithRunawayProcessKiller(RunawayProcessKillerExtension ext, string extensionId = "killRunawayProcess", bool enabled = true) @@ -118,7 +127,7 @@ namespace winswTests.Util str.AppendFormat(" {0}\n", ext.StopTimeout.TotalMilliseconds); str.AppendFormat(" {0}\n", ext.CheckWinSWEnvironmentVariable); str.Append(" \n"); - ExtensionXmls.Add(str.ToString()); + this.ExtensionXmls.Add(str.ToString()); return this; } @@ -129,10 +138,10 @@ namespace winswTests.Util xml.Append($""); - return WithRawEntry(xml.ToString()); + return this.WithRawEntry(xml.ToString()); } public ConfigXmlBuilder WithDelayedAutoStart() { - return WithRawEntry(""); + return this.WithRawEntry(""); } } } diff --git a/src/Test/winswTests/Util/DateTimeExtensions.cs b/src/Test/winswTests/Util/DateTimeExtensions.cs index dada47b..50c0a85 100644 --- a/src/Test/winswTests/Util/DateTimeExtensions.cs +++ b/src/Test/winswTests/Util/DateTimeExtensions.cs @@ -1,6 +1,6 @@ using System; -namespace winswTests.Util +namespace WinSW.Tests.Util { internal static class DateTimeExtensions { diff --git a/src/Test/winswTests/Util/FilesystemTestHelper.cs b/src/Test/winswTests/Util/FilesystemTestHelper.cs index ed63830..11324c4 100644 --- a/src/Test/winswTests/Util/FilesystemTestHelper.cs +++ b/src/Test/winswTests/Util/FilesystemTestHelper.cs @@ -1,9 +1,9 @@ using System; using System.IO; -namespace winswTests.Util +namespace WinSW.Tests.Util { - class FilesystemTestHelper + internal class FilesystemTestHelper { /// /// Creates a temporary directory for testing. diff --git a/src/Test/winswTests/Util/ServiceDescriptorAssert.cs b/src/Test/winswTests/Util/ServiceDescriptorAssert.cs index 1228286..e7940e6 100644 --- a/src/Test/winswTests/Util/ServiceDescriptorAssert.cs +++ b/src/Test/winswTests/Util/ServiceDescriptorAssert.cs @@ -1,16 +1,14 @@ using System.Collections.Generic; using System.Reflection; -using winsw; -using winsw.Configuration; +using WinSW.Configuration; using Xunit; -namespace winswTests.Util +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); diff --git a/src/stylecop.json b/src/stylecop.json new file mode 100644 index 0000000..5b778b3 --- /dev/null +++ b/src/stylecop.json @@ -0,0 +1,7 @@ +{ + "settings": { + "orderingRules": { + "usingDirectivesPlacement": "outsideNamespace" + } + } +} diff --git a/src/winsw.sln b/src/winsw.sln index b78983a..0c85504 100644 --- a/src/winsw.sln +++ b/src/winsw.sln @@ -1,12 +1,13 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30128.74 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winsw", "Core\ServiceWrapper\winsw.csproj", "{0DE77F55-ADE5-43C1-999A-0BC81153B039}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "winsw", "Core\ServiceWrapper\winsw.csproj", "{0DE77F55-ADE5-43C1-999A-0BC81153B039}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winswTests", "Test\winswTests\winswTests.csproj", "{93843402-842B-44B4-B303-AEE829BE0B43}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "winswTests", "Test\winswTests\winswTests.csproj", "{93843402-842B-44B4-B303-AEE829BE0B43}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedDirectoryMapper", "Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj", "{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharedDirectoryMapper", "Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj", "{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{077C2CEC-B687-4B53-86E9-C1A1BF5554E5}" EndProject @@ -14,12 +15,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{BC4A EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{5297623A-1A95-4F89-9AAE-DA634081EC86}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinSWCore", "Core\WinSWCore\WinSWCore.csproj", "{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinSWCore", "Core\WinSWCore\WinSWCore.csproj", "{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RunawayProcessKiller", "Plugins\RunawayProcessKiller\RunawayProcessKiller.csproj", "{57284B7A-82A4-407A-B706-EBEA6BF8EA13}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RunawayProcessKiller", "Plugins\RunawayProcessKiller\RunawayProcessKiller.csproj", "{57284B7A-82A4-407A-B706-EBEA6BF8EA13}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AA414F46-B863-473A-A0E0-C2971B3396AE}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig ..\samples\sample-complete.xml = ..\samples\sample-complete.xml ..\samples\sample-minimal.xml = ..\samples\sample-minimal.xml EndProjectSection @@ -83,4 +85,7 @@ Global {9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06} = {5297623A-1A95-4F89-9AAE-DA634081EC86} {57284B7A-82A4-407A-B706-EBEA6BF8EA13} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F9F8AFEA-196D-4041-8441-FABC3B730F9E} + EndGlobalSection EndGlobal diff --git a/src/winsw.sln.DotSettings b/src/winsw.sln.DotSettings deleted file mode 100644 index 45d451a..0000000 --- a/src/winsw.sln.DotSettings +++ /dev/null @@ -1,3 +0,0 @@ - - SW - UNC \ No newline at end of file