mirror of https://github.com/winsw/winsw
Fix code analysis warnings
parent
42a3b87aa1
commit
d08b72ceb3
|
@ -33,7 +33,7 @@ namespace WinSW.Configuration
|
||||||
|
|
||||||
public virtual string? ServiceAccountUserName => null;
|
public virtual string? ServiceAccountUserName => null;
|
||||||
|
|
||||||
public virtual Native.SC_ACTION[] FailureActions => new Native.SC_ACTION[0];
|
public virtual Native.SC_ACTION[] FailureActions => Array.Empty<Native.SC_ACTION>();
|
||||||
|
|
||||||
public virtual TimeSpan ResetFailureAfter => TimeSpan.FromDays(1);
|
public virtual TimeSpan ResetFailureAfter => TimeSpan.FromDays(1);
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ namespace WinSW.Configuration
|
||||||
// Service management
|
// Service management
|
||||||
public virtual ServiceStartMode StartMode => ServiceStartMode.Automatic;
|
public virtual ServiceStartMode StartMode => ServiceStartMode.Automatic;
|
||||||
|
|
||||||
public virtual string[] ServiceDependencies => new string[0];
|
public virtual string[] ServiceDependencies => Array.Empty<string>();
|
||||||
|
|
||||||
public virtual bool Interactive => false;
|
public virtual bool Interactive => false;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -96,6 +97,27 @@ namespace WinSW
|
||||||
return new XmlServiceConfig(dom);
|
return new XmlServiceConfig(dom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int SingleIntElement(XmlNode parent, string tagName, int defaultValue)
|
||||||
|
{
|
||||||
|
XmlNode? e = parent.SelectSingleNode(tagName);
|
||||||
|
|
||||||
|
return e is null ? defaultValue : int.Parse(e.InnerText, NumberFormatInfo.InvariantInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TimeSpan ParseTimeSpan(string v)
|
||||||
|
{
|
||||||
|
v = v.Trim();
|
||||||
|
foreach (var s in Suffix)
|
||||||
|
{
|
||||||
|
if (v.EndsWith(s.Key))
|
||||||
|
{
|
||||||
|
return TimeSpan.FromMilliseconds(int.Parse(v.Substring(0, v.Length - s.Key.Length).Trim(), NumberFormatInfo.InvariantInfo) * s.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TimeSpan.FromMilliseconds(int.Parse(v, NumberFormatInfo.InvariantInfo));
|
||||||
|
}
|
||||||
|
|
||||||
private string SingleElement(string tagName)
|
private string SingleElement(string tagName)
|
||||||
{
|
{
|
||||||
return this.SingleElement(tagName, false)!;
|
return this.SingleElement(tagName, false)!;
|
||||||
|
@ -119,31 +141,10 @@ namespace WinSW
|
||||||
return e is null ? defaultValue : bool.Parse(e.InnerText);
|
return e is null ? defaultValue : bool.Parse(e.InnerText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int SingleIntElement(XmlNode parent, string tagName, int defaultValue)
|
|
||||||
{
|
|
||||||
XmlNode? e = parent.SelectSingleNode(tagName);
|
|
||||||
|
|
||||||
return e is null ? defaultValue : int.Parse(e.InnerText);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TimeSpan SingleTimeSpanElement(XmlNode parent, string tagName, TimeSpan defaultValue)
|
private TimeSpan SingleTimeSpanElement(XmlNode parent, string tagName, TimeSpan defaultValue)
|
||||||
{
|
{
|
||||||
string? value = this.SingleElement(tagName, true);
|
string? value = this.SingleElement(tagName, true);
|
||||||
return value is null ? defaultValue : this.ParseTimeSpan(value);
|
return value is null ? defaultValue : ParseTimeSpan(value);
|
||||||
}
|
|
||||||
|
|
||||||
private TimeSpan ParseTimeSpan(string v)
|
|
||||||
{
|
|
||||||
v = v.Trim();
|
|
||||||
foreach (var s in Suffix)
|
|
||||||
{
|
|
||||||
if (v.EndsWith(s.Key))
|
|
||||||
{
|
|
||||||
return TimeSpan.FromMilliseconds(int.Parse(v.Substring(0, v.Length - s.Key.Length).Trim()) * s.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TimeSpan.FromMilliseconds(int.Parse(v));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<string, long> Suffix = new Dictionary<string, long>
|
private static readonly Dictionary<string, long> Suffix = new Dictionary<string, long>
|
||||||
|
@ -398,19 +399,19 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
|
|
||||||
var pattern = patternNode.InnerText;
|
var pattern = patternNode.InnerText;
|
||||||
int period = this.SingleIntElement(e, "period", 1);
|
int period = SingleIntElement(e, "period", 1);
|
||||||
return new TimeBasedRollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern, pattern, period);
|
return new TimeBasedRollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern, pattern, period);
|
||||||
|
|
||||||
case "roll-by-size":
|
case "roll-by-size":
|
||||||
sizeThreshold = this.SingleIntElement(e, "sizeThreshold", 10 * 1024) * SizeBasedRollingLogAppender.BytesPerKB;
|
sizeThreshold = SingleIntElement(e, "sizeThreshold", 10 * 1024) * SizeBasedRollingLogAppender.BytesPerKB;
|
||||||
int keepFiles = this.SingleIntElement(e, "keepFiles", SizeBasedRollingLogAppender.DefaultFilesToKeep);
|
int keepFiles = SingleIntElement(e, "keepFiles", SizeBasedRollingLogAppender.DefaultFilesToKeep);
|
||||||
return new SizeBasedRollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern, sizeThreshold, keepFiles);
|
return new SizeBasedRollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern, sizeThreshold, keepFiles);
|
||||||
|
|
||||||
case "append":
|
case "append":
|
||||||
return new DefaultLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern);
|
return new DefaultLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern);
|
||||||
|
|
||||||
case "roll-by-size-time":
|
case "roll-by-size-time":
|
||||||
sizeThreshold = this.SingleIntElement(e, "sizeThreshold", 10 * 1024) * RollingSizeTimeLogAppender.BytesPerKB;
|
sizeThreshold = SingleIntElement(e, "sizeThreshold", 10 * 1024) * RollingSizeTimeLogAppender.BytesPerKB;
|
||||||
XmlNode? filePatternNode = e.SelectSingleNode("pattern");
|
XmlNode? filePatternNode = e.SelectSingleNode("pattern");
|
||||||
if (filePatternNode is null)
|
if (filePatternNode is null)
|
||||||
{
|
{
|
||||||
|
@ -527,7 +528,7 @@ namespace WinSW
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
string? value = this.SingleElement("preshutdownTimeout", true);
|
string? value = this.SingleElement("preshutdownTimeout", true);
|
||||||
return value is null ? default : this.ParseTimeSpan(value);
|
return value is null ? default : ParseTimeSpan(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,7 +582,7 @@ namespace WinSW
|
||||||
XmlNodeList? childNodes = this.dom.SelectNodes("//onfailure");
|
XmlNodeList? childNodes = this.dom.SelectNodes("//onfailure");
|
||||||
if (childNodes is null)
|
if (childNodes is null)
|
||||||
{
|
{
|
||||||
return new SC_ACTION[0];
|
return Array.Empty<SC_ACTION>();
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_ACTION[] result = new SC_ACTION[childNodes.Count];
|
SC_ACTION[] result = new SC_ACTION[childNodes.Count];
|
||||||
|
@ -597,7 +598,7 @@ namespace WinSW
|
||||||
_ => throw new Exception("Invalid failure action: " + action)
|
_ => throw new Exception("Invalid failure action: " + action)
|
||||||
};
|
};
|
||||||
XmlAttribute? delay = node.Attributes["delay"];
|
XmlAttribute? delay = node.Attributes["delay"];
|
||||||
result[i] = new SC_ACTION(type, delay != null ? this.ParseTimeSpan(delay.Value) : TimeSpan.Zero);
|
result[i] = new SC_ACTION(type, delay != null ? ParseTimeSpan(delay.Value) : TimeSpan.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -106,7 +106,7 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
|
|
||||||
// Source: http://stackoverflow.com/questions/2764577/forcing-basic-authentication-in-webrequest
|
// Source: http://stackoverflow.com/questions/2764577/forcing-basic-authentication-in-webrequest
|
||||||
private void SetBasicAuthHeader(WebRequest request, string username, string password)
|
private static void SetBasicAuthHeader(WebRequest request, string username, string password)
|
||||||
{
|
{
|
||||||
string authInfo = username + ":" + password;
|
string authInfo = username + ":" + password;
|
||||||
authInfo = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(authInfo));
|
authInfo = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(authInfo));
|
||||||
|
@ -148,7 +148,7 @@ namespace WinSW
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AuthType.Basic:
|
case AuthType.Basic:
|
||||||
this.SetBasicAuthHeader(request, this.Username!, this.Password!);
|
SetBasicAuthHeader(request, this.Username!, this.Password!);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -166,7 +166,7 @@ namespace WinSW
|
||||||
string tmpFilePath = this.To + ".tmp";
|
string tmpFilePath = this.To + ".tmp";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (WebResponse response = await request.GetResponseAsync())
|
using (WebResponse response = await request.GetResponseAsync().ConfigureAwait(false))
|
||||||
using (Stream responseStream = response.GetResponseStream())
|
using (Stream responseStream = response.GetResponseStream())
|
||||||
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
|
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
|
||||||
{
|
{
|
||||||
|
@ -175,7 +175,7 @@ namespace WinSW
|
||||||
lastModified = ((HttpWebResponse)response).LastModified;
|
lastModified = ((HttpWebResponse)response).LastModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
await responseStream.CopyToAsync(tmpStream);
|
await responseStream.CopyToAsync(tmpStream).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileHelper.MoveOrReplaceFile(this.To + ".tmp", this.To);
|
FileHelper.MoveOrReplaceFile(this.To + ".tmp", this.To);
|
||||||
|
|
|
@ -19,6 +19,33 @@ namespace WinSW.Extensions
|
||||||
this.Extensions = new Dictionary<string, IWinSWExtension>();
|
this.Extensions = new Dictionary<string, IWinSWExtension>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IWinSWExtension CreateExtensionInstance(string id, string className)
|
||||||
|
{
|
||||||
|
object created;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Type? t = Type.GetType(className);
|
||||||
|
if (t is null)
|
||||||
|
{
|
||||||
|
throw new ExtensionException(id, "Class " + className + " does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
created = Activator.CreateInstance(t)!;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new ExtensionException(id, "Cannot load the class by name: " + className, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(created is IWinSWExtension extension))
|
||||||
|
{
|
||||||
|
throw new ExtensionException(id, "The loaded class is not a WinSW extension: " + className + ". Type is " + created.GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Notifies all extensions that the wrapper is being started.
|
/// Notifies all extensions that the wrapper is being started.
|
||||||
/// They are supposed to run the initialization logic.
|
/// They are supposed to run the initialization logic.
|
||||||
|
@ -137,7 +164,7 @@ namespace WinSW.Extensions
|
||||||
var descriptor = WinSWExtensionDescriptor.FromXml(configNode);
|
var descriptor = WinSWExtensionDescriptor.FromXml(configNode);
|
||||||
if (descriptor.Enabled)
|
if (descriptor.Enabled)
|
||||||
{
|
{
|
||||||
IWinSWExtension extension = this.CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
|
IWinSWExtension extension = CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
|
||||||
extension.Descriptor = descriptor;
|
extension.Descriptor = descriptor;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -146,7 +173,7 @@ namespace WinSW.Extensions
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{ // Consider any unexpected exception as fatal
|
{ // Consider any unexpected exception as fatal
|
||||||
Log.Fatal("Failed to configure the extension " + id, ex);
|
Log.Fatal("Failed to configure the extension " + id, ex);
|
||||||
throw ex;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Extensions.Add(id, extension);
|
this.Extensions.Add(id, extension);
|
||||||
|
@ -158,33 +185,6 @@ namespace WinSW.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IWinSWExtension CreateExtensionInstance(string id, string className)
|
|
||||||
{
|
|
||||||
object created;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Type? t = Type.GetType(className);
|
|
||||||
if (t is null)
|
|
||||||
{
|
|
||||||
throw new ExtensionException(id, "Class " + className + " does not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
created = Activator.CreateInstance(t)!;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new ExtensionException(id, "Cannot load the class by name: " + className, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(created is IWinSWExtension extension))
|
|
||||||
{
|
|
||||||
throw new ExtensionException(id, "The loaded class is not a WinSW extension: " + className + ". Type is " + created.GetType());
|
|
||||||
}
|
|
||||||
|
|
||||||
return extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System.Xml;
|
||||||
|
|
||||||
namespace WinSW.Util
|
namespace WinSW.Util
|
||||||
{
|
{
|
||||||
public class XmlHelper
|
public static class XmlHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves a single string element
|
/// Retrieves a single string element
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
/// Class, which contains generic information about WinSW runtime.
|
/// Class, which contains generic information about WinSW runtime.
|
||||||
/// This information can be used by the service and extensions.
|
/// This information can be used by the service and extensions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WinSWSystem
|
public static class WinSWSystem
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prefix for all environment variables being injected for WinSW
|
/// Prefix for all environment variables being injected for WinSW
|
||||||
|
|
Loading…
Reference in New Issue