diff --git a/src/Core/ServiceWrapper/Logging/WrapperServiceEventLogProvider.cs b/src/Core/ServiceWrapper/Logging/WrapperServiceEventLogProvider.cs index f051d32..be7cad5 100644 --- a/src/Core/ServiceWrapper/Logging/WrapperServiceEventLogProvider.cs +++ b/src/Core/ServiceWrapper/Logging/WrapperServiceEventLogProvider.cs @@ -7,11 +7,11 @@ namespace winsw.Logging /// public class WrapperServiceEventLogProvider : IServiceEventLogProvider { - public WrapperService service { get; set; } + public WrapperService? service { get; set; } - public EventLog locate() + public EventLog? locate() { - WrapperService _service = service; + WrapperService? _service = service; if (_service != null && !_service.IsShuttingDown) { return _service.EventLog; diff --git a/src/Core/ServiceWrapper/Main.cs b/src/Core/ServiceWrapper/Main.cs index 20cd026..4602453 100644 --- a/src/Core/ServiceWrapper/Main.cs +++ b/src/Core/ServiceWrapper/Main.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; using System.Runtime.InteropServices; @@ -28,7 +29,7 @@ namespace winsw private readonly Process _process = new Process(); private readonly ServiceDescriptor _descriptor; - private Dictionary _envs; + private Dictionary? _envs; internal WinSWExtensionManager ExtensionManager { get; private set; } @@ -52,7 +53,7 @@ namespace winsw /// /// The version will be taken from /// - public static Version Version => Assembly.GetExecutingAssembly().GetName().Version; + public static Version Version => Assembly.GetExecutingAssembly().GetName().Version!; /// /// Indicates that the system is shutting down. @@ -92,7 +93,7 @@ namespace winsw { using (var tr = new StreamReader(file, Encoding.UTF8)) { - string line; + string? line; while ((line = tr.ReadLine()) != null) { LogEvent("Handling copy: " + line); @@ -223,7 +224,7 @@ namespace winsw } } - string startarguments = _descriptor.Startarguments; + string? startarguments = _descriptor.Startarguments; if (startarguments == null) { @@ -282,7 +283,7 @@ namespace winsw /// private void StopIt() { - string stoparguments = _descriptor.Stoparguments; + string? stoparguments = _descriptor.Stoparguments; LogEvent("Stopping " + _descriptor.Id); Log.Info("Stopping " + _descriptor.Id); _orderlyShutdown = true; @@ -307,7 +308,7 @@ namespace winsw stoparguments += " " + _descriptor.Arguments; Process stopProcess = new Process(); - string executable = _descriptor.StopExecutable; + string? executable = _descriptor.StopExecutable; if (executable == null) { @@ -399,7 +400,7 @@ namespace winsw Advapi32.SetServiceStatus(handle, ref _wrapperServiceStatus); } - private void StartProcess(Process processToStart, string arguments, string executable, LogHandler logHandler, bool redirectStdin) + private void StartProcess(Process processToStart, string arguments, string executable, LogHandler? logHandler, bool redirectStdin) { // Define handler of the completed process void OnProcessCompleted(Process proc) @@ -470,6 +471,7 @@ namespace winsw } } + [DoesNotReturn] private static void ThrowNoSuchService() { throw new WmiException(ReturnValue.NoSuchService); @@ -483,7 +485,7 @@ namespace winsw /// Service descriptor. If null, it will be initialized within the method. /// In such case configs will be loaded from the XML Configuration File. /// Any unhandled exception - public static void Run(string[] _args, ServiceDescriptor descriptor = null) + public static void Run(string[] _args, ServiceDescriptor? descriptor = null) { bool isCLIMode = _args.Length > 0; @@ -538,8 +540,9 @@ namespace winsw throw new Exception("Installation failure: Service with id '" + d.Id + "' already exists"); } - string username = null, password = null; - bool setallowlogonasaserviceright = false; + string? username = null; + string? password = null; + bool setallowlogonasaserviceright = false; // This variable is very readable. if (args.Count > 1 && args[1] == "/p") { // we expected username/password on stdin @@ -568,7 +571,7 @@ namespace winsw if (setallowlogonasaserviceright) { - LogonAsAService.AddLogonAsAServiceRight(username); + LogonAsAService.AddLogonAsAServiceRight(username!); } svc.Create( diff --git a/src/Core/ServiceWrapper/NullableAttributes.cs b/src/Core/ServiceWrapper/NullableAttributes.cs new file mode 100644 index 0000000..45b5ff2 --- /dev/null +++ b/src/Core/ServiceWrapper/NullableAttributes.cs @@ -0,0 +1,8 @@ +#if !NETCOREAPP +namespace System.Diagnostics.CodeAnalysis +{ + /// Applied to a method that will never return under any circumstance. + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + internal sealed class DoesNotReturnAttribute : Attribute { } +} +#endif diff --git a/src/Core/ServiceWrapper/SigIntHelper.cs b/src/Core/ServiceWrapper/SigIntHelper.cs index 7dfabe6..4134740 100644 --- a/src/Core/ServiceWrapper/SigIntHelper.cs +++ b/src/Core/ServiceWrapper/SigIntHelper.cs @@ -15,7 +15,7 @@ namespace winsw private static extern bool FreeConsole(); [DllImport(KERNEL32)] - private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add); + private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate? HandlerRoutine, bool Add); // Delegate type to be used as the Handler Routine for SCCH private delegate bool ConsoleCtrlDelegate(CtrlTypes CtrlType); diff --git a/src/Core/ServiceWrapper/winsw.csproj b/src/Core/ServiceWrapper/winsw.csproj index 4a54097..cd4d7c5 100644 --- a/src/Core/ServiceWrapper/winsw.csproj +++ b/src/Core/ServiceWrapper/winsw.csproj @@ -3,6 +3,8 @@ Exe net20;net40;net461;netcoreapp3.1 + latest + enable Windows Service Wrapper Allows arbitrary process to run as a Windows service by wrapping it. diff --git a/src/Core/WinSWCore/Logging/IServiceEventLogProvider.cs b/src/Core/WinSWCore/Logging/IServiceEventLogProvider.cs index c590b47..f35d6e9 100644 --- a/src/Core/WinSWCore/Logging/IServiceEventLogProvider.cs +++ b/src/Core/WinSWCore/Logging/IServiceEventLogProvider.cs @@ -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/Native/Kernel32.cs b/src/Core/WinSWCore/Native/Kernel32.cs index abc7c85..14dd870 100755 --- a/src/Core/WinSWCore/Native/Kernel32.cs +++ b/src/Core/WinSWCore/Native/Kernel32.cs @@ -13,12 +13,17 @@ namespace winsw.Native public static extern bool SetStdHandle(int nStdHandle, SafeFileHandle handle); [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool CreateProcess(string lpApplicationName, - string lpCommandLine, IntPtr lpProcessAttributes, - IntPtr lpThreadAttributes, bool bInheritHandles, - uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, - [In] ref STARTUPINFO lpStartupInfo, - out PROCESS_INFORMATION lpProcessInformation); + public static extern bool CreateProcess( + string? lpApplicationName, + string lpCommandLine, + IntPtr lpProcessAttributes, + IntPtr lpThreadAttributes, + bool bInheritHandles, + uint dwCreationFlags, + IntPtr lpEnvironment, + string? lpCurrentDirectory, + [In] ref STARTUPINFO lpStartupInfo, + out PROCESS_INFORMATION lpProcessInformation); [DllImport("kernel32.dll")] public static extern int GetLastError(); diff --git a/src/Core/WinSWCore/WmiSchema.cs b/src/Core/WinSWCore/WmiSchema.cs index 4a241e3..bfa55a1 100755 --- a/src/Core/WinSWCore/WmiSchema.cs +++ b/src/Core/WinSWCore/WmiSchema.cs @@ -48,7 +48,7 @@ namespace WMI public interface Win32Services : IWmiCollection { // ReturnValue Create(bool desktopInteract, string displayName, int errorControl, string loadOrderGroup, string loadOrderGroupDependencies, string name, string pathName, string serviceDependencies, string serviceType, string startMode, string startName, string startPassword); - void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, StartMode startMode, bool desktopInteract, string startName, string startPassword, string[] serviceDependencies); + void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, StartMode startMode, bool desktopInteract, string? startName, string? startPassword, string[] serviceDependencies); void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, StartMode startMode, bool desktopInteract, string[] serviceDependencies); diff --git a/src/Plugins/RunawayProcessKiller/RunawayProcessKiller.csproj b/src/Plugins/RunawayProcessKiller/RunawayProcessKiller.csproj index 7bbde10..7618eac 100644 --- a/src/Plugins/RunawayProcessKiller/RunawayProcessKiller.csproj +++ b/src/Plugins/RunawayProcessKiller/RunawayProcessKiller.csproj @@ -2,6 +2,8 @@ net20;net40;net461;netcoreapp3.1 + latest + enable winsw.Plugins.RunawayProcessKiller true diff --git a/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs b/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs index 974cfa3..9906c62 100644 --- a/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs +++ b/src/Plugins/RunawayProcessKiller/RunawayProcessKillerExtension.cs @@ -40,12 +40,16 @@ namespace winsw.Plugins.RunawayProcessKiller private static readonly ILog Logger = LogManager.GetLogger(typeof(RunawayProcessKillerExtension)); +#pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. public RunawayProcessKillerExtension() +#pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. { // Default initializer } +#pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. public RunawayProcessKillerExtension(string pidfile, int stopTimeoutMs = 5000, bool stopParentFirst = false, bool checkWinSWEnvironmentVariable = true) +#pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. { this.Pidfile = pidfile; this.StopTimeout = TimeSpan.FromMilliseconds(stopTimeoutMs); @@ -57,9 +61,9 @@ 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))); - StopParentProcessFirst = bool.Parse(XmlHelper.SingleElement(node, "stopParentFirst", false)); + Pidfile = XmlHelper.SingleElement(node, "pidfile", false)!; + StopTimeout = TimeSpan.FromMilliseconds(int.Parse(XmlHelper.SingleElement(node, "stopTimeout", false)!)); + StopParentProcessFirst = bool.Parse(XmlHelper.SingleElement(node, "stopParentFirst", false)!); ServiceId = descriptor.Id; // TODO: Consider making it documented var checkWinSWEnvironmentVariable = XmlHelper.SingleElement(node, "checkWinSWEnvironmentVariable", true); @@ -117,7 +121,7 @@ namespace winsw.Plugins.RunawayProcessKiller } // Ensure the process references the service - string affiliatedServiceId; + string? affiliatedServiceId; // TODO: This method is not ideal since it works only for vars explicitly mentioned in the start info // No Windows 10- compatible solution for EnvVars retrieval, see https://blog.gapotchenko.com/eazfuscator.net/reading-environment-variables StringDictionary previousProcessEnvVars = proc.StartInfo.EnvironmentVariables; diff --git a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs index 27d6f74..d67a78b 100644 --- a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs +++ b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.cs @@ -28,12 +28,12 @@ namespace winsw.Plugins.SharedDirectoryMapper public override void Configure(ServiceDescriptor descriptor, XmlNode node) { - var nodes = XmlHelper.SingleNode(node, "mapping", false).SelectNodes("map"); - if (nodes != null) + var mapNodes = XmlHelper.SingleNode(node, "mapping", false)!.SelectNodes("map"); + if (mapNodes != null) { - foreach (XmlNode mapNode in nodes) + for (int i = 0; i < mapNodes.Count; i++) { - if (mapNode is XmlElement mapElement) + if (mapNodes[i] is XmlElement mapElement) { var config = SharedDirectoryMapperConfig.FromXml(mapElement); _entries.Add(config); diff --git a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.csproj b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.csproj index 6d1aebc..b3a5f9f 100644 --- a/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.csproj +++ b/src/Plugins/SharedDirectoryMapper/SharedDirectoryMapper.csproj @@ -2,6 +2,8 @@ net20;net40;net461;netcoreapp3.1 + latest + enable winsw.Plugins.SharedDirectoryMapper true