Ensure basic console logging

pull/726/head
NextTurn 2020-09-06 00:00:00 +08:00 committed by Next Turn
parent 12525cc8fc
commit 2ab79083d4
34 changed files with 282 additions and 296 deletions

View File

@ -102,7 +102,7 @@ namespace WinSW
private static int SingleIntElement(XmlNode parent, string tagName, int defaultValue)
{
XmlNode? e = parent.SelectSingleNode(tagName);
var e = parent.SelectSingleNode(tagName);
return e is null ? defaultValue : int.Parse(e.InnerText, NumberFormatInfo.InvariantInfo);
}
@ -128,13 +128,13 @@ namespace WinSW
private string? SingleElementOrNull(string tagName)
{
XmlNode? n = this.root.SelectSingleNode(tagName);
var n = this.root.SelectSingleNode(tagName);
return n is null ? null : Environment.ExpandEnvironmentVariables(n.InnerText);
}
private bool SingleBoolElementOrDefault(string tagName, bool defaultValue)
{
XmlNode? e = this.root.SelectSingleNode(tagName);
var e = this.root.SelectSingleNode(tagName);
return e is null ? defaultValue : bool.Parse(e.InnerText);
}
@ -208,14 +208,14 @@ namespace WinSW
{
get
{
XmlNode? argumentNode = this.ExtensionsConfiguration;
XmlNodeList? extensions = argumentNode?.SelectNodes("extension");
var argumentNode = this.ExtensionsConfiguration;
var extensions = argumentNode?.SelectNodes("extension");
if (extensions is null)
{
return new List<string>(0);
}
List<string> result = new List<string>(extensions.Count);
var result = new List<string>(extensions.Count);
for (int i = 0; i < extensions.Count; i++)
{
result.Add(XmlHelper.SingleAttribute<string>((XmlElement)extensions[i]!, "id"));
@ -239,7 +239,7 @@ namespace WinSW
string? mode = null;
// first, backward compatibility with older configuration
XmlElement? e = (XmlElement?)this.root.SelectSingleNode("logmode");
var e = (XmlElement?)this.root.SelectSingleNode("logmode");
if (e != null)
{
mode = e.InnerText;
@ -272,7 +272,7 @@ namespace WinSW
{
get
{
XmlElement? e = (XmlElement?)this.root.SelectSingleNode("logmode");
var e = (XmlElement?)this.root.SelectSingleNode("logmode");
// this is more modern way, to support nested elements as configuration
e ??= (XmlElement?)this.root.SelectSingleNode("log")!; // WARNING: NRE
@ -293,13 +293,13 @@ namespace WinSW
return new RollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern);
case "roll-by-time":
XmlNode? patternNode = e.SelectSingleNode("pattern");
var patternNode = e.SelectSingleNode("pattern");
if (patternNode is null)
{
throw new InvalidDataException("Time Based rolling policy is specified but no pattern can be found in configuration XML.");
}
var pattern = patternNode.InnerText;
string? pattern = patternNode.InnerText;
int period = SingleIntElement(e, "period", 1);
return new TimeBasedRollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern, pattern, period);
@ -313,18 +313,18 @@ namespace WinSW
case "roll-by-size-time":
sizeThreshold = SingleIntElement(e, "sizeThreshold", 10 * 1024) * RollingSizeTimeLogAppender.BytesPerKB;
XmlNode? filePatternNode = e.SelectSingleNode("pattern");
var filePatternNode = e.SelectSingleNode("pattern");
if (filePatternNode is null)
{
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but no pattern can be found in configuration XML.");
}
XmlNode? autoRollAtTimeNode = e.SelectSingleNode("autoRollAtTime");
var autoRollAtTimeNode = e.SelectSingleNode("autoRollAtTime");
TimeSpan? autoRollAtTime = null;
if (autoRollAtTimeNode != null)
{
// validate it
if (!TimeSpan.TryParse(autoRollAtTimeNode.InnerText, out TimeSpan autoRollAtTimeValue))
if (!TimeSpan.TryParse(autoRollAtTimeNode.InnerText, out var 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.");
}
@ -332,7 +332,7 @@ namespace WinSW
autoRollAtTime = autoRollAtTimeValue;
}
XmlNode? zipolderthannumdaysNode = e.SelectSingleNode("zipOlderThanNumDays");
var zipolderthannumdaysNode = e.SelectSingleNode("zipOlderThanNumDays");
int? zipolderthannumdays = null;
if (zipolderthannumdaysNode != null)
{
@ -345,7 +345,7 @@ namespace WinSW
zipolderthannumdays = zipolderthannumdaysValue;
}
XmlNode? zipdateformatNode = e.SelectSingleNode("zipDateFormat");
var zipdateformatNode = e.SelectSingleNode("zipDateFormat");
string zipdateformat = zipdateformatNode is null ? "yyyyMM" : zipdateformatNode.InnerText;
return new RollingSizeTimeLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern, sizeThreshold, filePatternNode.InnerText, autoRollAtTime, zipolderthannumdays, zipdateformat);
@ -363,7 +363,7 @@ namespace WinSW
{
get
{
XmlNodeList? nodeList = this.root.SelectNodes("depend");
var nodeList = this.root.SelectNodes("depend");
if (nodeList is null)
{
return base.ServiceDependencies;
@ -404,7 +404,7 @@ namespace WinSW
}
catch (ArgumentException e)
{
StringBuilder builder = new StringBuilder();
var builder = new StringBuilder();
builder.AppendLine("Start mode in XML must be one of the following:");
foreach (string sm in Enum.GetNames(typeof(ServiceStartMode)))
{
@ -457,13 +457,13 @@ namespace WinSW
{
get
{
XmlNodeList? nodeList = this.root.SelectNodes("download");
var nodeList = this.root.SelectNodes("download");
if (nodeList is null)
{
return base.Downloads;
}
List<Download> result = new List<Download>(nodeList.Count);
var result = new List<Download>(nodeList.Count);
for (int i = 0; i < nodeList.Count; i++)
{
if (nodeList[i] is XmlElement element)
@ -480,25 +480,25 @@ namespace WinSW
{
get
{
XmlNodeList? childNodes = this.root.SelectNodes("onfailure");
var childNodes = this.root.SelectNodes("onfailure");
if (childNodes is null)
{
return Array.Empty<SC_ACTION>();
}
SC_ACTION[] result = new SC_ACTION[childNodes.Count];
var result = new SC_ACTION[childNodes.Count];
for (int i = 0; i < childNodes.Count; i++)
{
XmlNode node = childNodes[i]!;
var node = childNodes[i]!;
string action = node.Attributes!["action"]?.Value ?? throw new InvalidDataException("'action' is missing");
SC_ACTION_TYPE type = action switch
var type = action switch
{
"restart" => SC_ACTION_TYPE.SC_ACTION_RESTART,
"none" => SC_ACTION_TYPE.SC_ACTION_NONE,
"reboot" => SC_ACTION_TYPE.SC_ACTION_REBOOT,
_ => throw new Exception("Invalid failure action: " + action)
};
XmlAttribute? delay = node.Attributes["delay"];
var delay = node.Attributes["delay"];
result[i] = new SC_ACTION(type, delay != null ? ParseTimeSpan(delay.Value) : TimeSpan.Zero);
}
@ -510,11 +510,11 @@ namespace WinSW
protected string? GetServiceAccountPart(string subNodeName)
{
XmlNode? node = this.root.SelectSingleNode("serviceaccount");
var node = this.root.SelectSingleNode("serviceaccount");
if (node != null)
{
XmlNode? subNode = node.SelectSingleNode(subNodeName);
var subNode = node.SelectSingleNode(subNodeName);
if (subNode != null)
{
return subNode.InnerText;
@ -583,11 +583,11 @@ namespace WinSW
private Dictionary<string, string> LoadEnvironmentVariables()
{
XmlNodeList nodeList = this.root.SelectNodes("env")!;
Dictionary<string, string> environment = new Dictionary<string, string>(nodeList.Count);
var nodeList = this.root.SelectNodes("env")!;
var environment = new Dictionary<string, string>(nodeList.Count);
for (int i = 0; i < nodeList.Count; i++)
{
XmlNode node = nodeList[i]!;
var node = nodeList[i]!;
string key = node.Attributes!["name"]?.Value ?? throw new InvalidDataException("'name' is missing");
string value = Environment.ExpandEnvironmentVariables(node.Attributes["value"]?.Value ?? throw new InvalidDataException("'value' is missing"));
environment[key] = value;
@ -600,7 +600,7 @@ namespace WinSW
private ProcessCommand GetProcessCommand(string name)
{
XmlNode? node = this.root.SelectSingleNode(name);
var node = this.root.SelectSingleNode(name);
return node is null ? default : new ProcessCommand
{
Executable = GetInnerText(Names.Executable),

View File

@ -121,10 +121,10 @@ namespace WinSW
/// </exception>
public async Task PerformAsync()
{
WebRequest request = WebRequest.Create(this.From);
var request = WebRequest.Create(this.From);
if (!string.IsNullOrEmpty(this.Proxy))
{
CustomProxyInformation proxyInformation = new CustomProxyInformation(this.Proxy!);
var proxyInformation = new CustomProxyInformation(this.Proxy!);
if (proxyInformation.Credentials != null)
{
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
@ -166,9 +166,9 @@ namespace WinSW
string tmpFilePath = this.To + ".tmp";
try
{
using (WebResponse response = await request.GetResponseAsync().ConfigureAwait(false))
using (Stream responseStream = response.GetResponseStream())
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
using (var response = await request.GetResponseAsync().ConfigureAwait(false))
using (var responseStream = response.GetResponseStream())
using (var tmpStream = new FileStream(tmpFilePath, FileMode.Create))
{
if (supportsIfModifiedSince)
{

View File

@ -25,7 +25,7 @@ namespace WinSW.Extensions
try
{
Type? t = Type.GetType(className);
var t = Type.GetType(className);
if (t is null)
{
throw new ExtensionException(id, "Class " + className + " does not exist");
@ -154,8 +154,8 @@ namespace WinSW.Extensions
throw new ExtensionException(id, "Extension has been already loaded");
}
XmlNode? extensionsConfig = this.ServiceConfig.ExtensionsConfiguration;
XmlElement? configNode = extensionsConfig is null ? null : extensionsConfig.SelectSingleNode("extension[@id='" + id + "'][1]") as XmlElement;
var extensionsConfig = this.ServiceConfig.ExtensionsConfiguration;
var configNode = extensionsConfig is null ? null : extensionsConfig.SelectSingleNode("extension[@id='" + id + "'][1]") as XmlElement;
if (configNode is null)
{
throw new ExtensionException(id, "Cannot get the configuration entry");
@ -164,7 +164,7 @@ namespace WinSW.Extensions
var descriptor = WinSWExtensionDescriptor.FromXml(configNode);
if (descriptor.Enabled)
{
IWinSWExtension extension = CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
var extension = CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
extension.Descriptor = descriptor;
try
{

View File

@ -243,10 +243,10 @@ namespace WinSW
/// </summary>
private async Task CopyStreamWithDateRotationAsync(StreamReader reader, string ext)
{
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.Pattern, this.Period);
var periodicRollingCalendar = new PeriodicRollingCalendar(this.Pattern, this.Period);
periodicRollingCalendar.Init();
StreamWriter writer = this.CreateWriter(new FileStream(this.BaseLogFileName + "_" + periodicRollingCalendar.Format + ext, FileMode.Append));
var writer = this.CreateWriter(new FileStream(this.BaseLogFileName + "_" + periodicRollingCalendar.Format + ext, FileMode.Append));
string? line;
while ((line = await reader.ReadLineAsync()) != null)
{
@ -302,7 +302,7 @@ namespace WinSW
/// </summary>
private async Task CopyStreamWithRotationAsync(StreamReader reader, string ext)
{
StreamWriter writer = this.CreateWriter(new FileStream(this.BaseLogFileName + ext, FileMode.Append));
var writer = this.CreateWriter(new FileStream(this.BaseLogFileName + ext, FileMode.Append));
long fileLength = new FileInfo(this.BaseLogFileName + ext).Length;
string? line;
@ -426,20 +426,20 @@ namespace WinSW
private async Task CopyStreamWithRotationAsync(StreamReader reader, string extension)
{
// 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();
object? fileLock = new object();
var baseDirectory = Path.GetDirectoryName(this.BaseLogFileName)!;
var baseFileName = Path.GetFileName(this.BaseLogFileName);
var logFile = this.BaseLogFileName + extension;
string? baseDirectory = Path.GetDirectoryName(this.BaseLogFileName)!;
string? baseFileName = Path.GetFileName(this.BaseLogFileName);
string? logFile = this.BaseLogFileName + extension;
var writer = this.CreateWriter(new FileStream(logFile, FileMode.Append));
var fileLength = new FileInfo(logFile).Length;
long 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 (this.AutoRollAtTime is TimeSpan autoRollAtTime)
{
// Run at start
var tickTime = this.SetupRollTimer(autoRollAtTime);
double tickTime = this.SetupRollTimer(autoRollAtTime);
var timer = new System.Timers.Timer(tickTime);
timer.Elapsed += (_, _) =>
{
@ -451,8 +451,8 @@ namespace WinSW
writer.Dispose();
var now = DateTime.Now.AddDays(-1);
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));
int nextFileNumber = this.GetNextFileNumber(extension, baseDirectory, baseFileName, now);
string? nextFileName = Path.Combine(baseDirectory, string.Format("{0}.{1}.#{2:D4}{3}", baseFileName, now.ToString(this.FilePattern), nextFileNumber, extension));
File.Move(logFile, nextFileName);
writer = this.CreateWriter(new FileStream(logFile, FileMode.Create));
@ -488,8 +488,8 @@ namespace WinSW
{
// roll file
var now = DateTime.Now;
var nextFileNumber = this.GetNextFileNumber(extension, baseDirectory, baseFileName, now);
var nextFileName = Path.Combine(
int nextFileNumber = this.GetNextFileNumber(extension, baseDirectory, baseFileName, now);
string? nextFileName = Path.Combine(
baseDirectory,
string.Format("{0}.{1}.#{2:D4}{3}", baseFileName, now.ToString(this.FilePattern), nextFileNumber, extension));
File.Move(logFile, nextFileName);
@ -589,21 +589,21 @@ 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(this.FilePattern), ext));
int nextFileNumber = 0;
string[]? files = Directory.GetFiles(baseDirectory, string.Format("{0}.{1}.#*{2}", baseFileName, now.ToString(this.FilePattern), ext));
if (files.Length == 0)
{
nextFileNumber = 1;
}
else
{
foreach (var f in files)
foreach (string? f in files)
{
try
{
var filenameOnly = Path.GetFileNameWithoutExtension(f);
var hashIndex = filenameOnly.IndexOf('#');
var lastNumberAsString = filenameOnly.Substring(hashIndex + 1, 4);
string? filenameOnly = Path.GetFileNameWithoutExtension(f);
int hashIndex = filenameOnly.IndexOf('#');
string? lastNumberAsString = filenameOnly.Substring(hashIndex + 1, 4);
if (int.TryParse(lastNumberAsString, out int lastNumber))
{
if (lastNumber > nextFileNumber)

View File

@ -20,7 +20,7 @@ namespace WinSW.Native
IntPtr.Zero,
ref inBufferSize);
IntPtr inBuffer = Marshal.AllocCoTaskMem(inBufferSize);
var inBuffer = Marshal.AllocCoTaskMem(inBufferSize);
try
{
if (!CredPackAuthenticationBuffer(
@ -33,7 +33,7 @@ namespace WinSW.Native
Throw.Command.Win32Exception("Failed to pack auth buffer.");
}
CREDUI_INFO info = new CREDUI_INFO
var info = new CREDUI_INFO
{
Size = Marshal.SizeOf(typeof(CREDUI_INFO)),
CaptionText = caption,
@ -47,7 +47,7 @@ namespace WinSW.Native
ref authPackage,
inBuffer,
inBufferSize,
out IntPtr outBuffer,
out var outBuffer,
out uint outBufferSize,
ref save,
CREDUIWIN_GENERIC);

View File

@ -11,24 +11,24 @@ namespace WinSW.Native
/// <exception cref="CommandException" />
internal static unsafe bool UpdateCompanyName(string path, string outputPath, string companyName)
{
IntPtr module = LoadLibraryW(path);
var module = LoadLibraryW(path);
try
{
IntPtr verInfo = FindResourceW(module, VS_VERSION_INFO, RT_VERSION);
var verInfo = FindResourceW(module, VS_VERSION_INFO, RT_VERSION);
if (verInfo == IntPtr.Zero)
{
Exit();
}
IntPtr resData = LoadResource(module, verInfo);
var resData = LoadResource(module, verInfo);
if (resData == IntPtr.Zero)
{
Exit();
}
IntPtr resAddr = LockResource(resData);
var resAddr = LockResource(resData);
IntPtr address = resAddr;
var address = resAddr;
int offset = 0;
short length = ((short*)address)[0];
@ -81,7 +81,7 @@ namespace WinSW.Native
int newLength = companyName.Length + 1;
Debug.Assert(newLength > 12 && newLength <= 16);
IntPtr newAddress = Marshal.AllocHGlobal(length);
var newAddress = Marshal.AllocHGlobal(length);
try
{
Buffer.MemoryCopy((void*)resAddr, (void*)newAddress, length, length);
@ -94,7 +94,7 @@ namespace WinSW.Native
File.Copy(path, outputPath, true);
IntPtr update = BeginUpdateResourceW(outputPath, false);
var update = BeginUpdateResourceW(outputPath, false);
if (update == IntPtr.Zero)
{
Exit();

View File

@ -11,7 +11,7 @@ namespace WinSW.Native
/// <exception cref="Win32Exception" />
internal static void AddServiceLogonRight(ref string userName)
{
IntPtr sid = GetAccountSid(ref userName);
var sid = GetAccountSid(ref userName);
try
{
@ -36,7 +36,7 @@ namespace WinSW.Native
_ = LookupAccountName(null, accountName, IntPtr.Zero, ref sidSize, null, ref domainNameLength, out _);
IntPtr sid = Marshal.AllocHGlobal(sidSize);
var sid = Marshal.AllocHGlobal(sidSize);
try
{
string? domainName = domainNameLength == 0 ? null : new string('\0', domainNameLength - 1);
@ -64,7 +64,7 @@ namespace WinSW.Native
/// <exception cref="Win32Exception" />
private static void AddAccountRight(IntPtr sid, string rightName)
{
uint status = LsaOpenPolicy(IntPtr.Zero, default, PolicyAccess.ALL_ACCESS, out IntPtr policyHandle);
uint status = LsaOpenPolicy(IntPtr.Zero, default, PolicyAccess.ALL_ACCESS, out var policyHandle);
if (status != 0)
{
throw new Win32Exception(LsaNtStatusToWinError(status));
@ -72,7 +72,7 @@ namespace WinSW.Native
try
{
LSA_UNICODE_STRING userRight = new LSA_UNICODE_STRING
var userRight = new LSA_UNICODE_STRING
{
Buffer = rightName,
Length = (ushort)(rightName.Length * sizeof(char)),

View File

@ -58,7 +58,7 @@ namespace WinSW.Native
/// <exception cref="CommandException" />
internal static ServiceManager Open(ServiceManagerAccess access = ServiceManagerAccess.All)
{
IntPtr handle = OpenSCManager(null, null, access);
var handle = OpenSCManager(null, null, access);
if (handle == IntPtr.Zero)
{
Throw.Command.Win32Exception("Failed to open the service control manager database.");
@ -77,7 +77,7 @@ namespace WinSW.Native
string? username,
string? password)
{
IntPtr handle = ServiceApis.CreateService(
var handle = ServiceApis.CreateService(
this.handle,
serviceName,
displayName,
@ -113,7 +113,7 @@ namespace WinSW.Native
out _,
ref resume);
IntPtr services = Marshal.AllocHGlobal(bytesNeeded);
var services = Marshal.AllocHGlobal(bytesNeeded);
try
{
if (!EnumServicesStatus(
@ -141,7 +141,7 @@ namespace WinSW.Native
/// <exception cref="CommandException" />
internal unsafe Service OpenService(char* serviceName, ServiceAccess access = ServiceAccess.All)
{
IntPtr serviceHandle = ServiceApis.OpenService(this.handle, serviceName, access);
var serviceHandle = ServiceApis.OpenService(this.handle, serviceName, access);
if (serviceHandle == IntPtr.Zero)
{
Throw.Command.Win32Exception("Failed to open the service.");
@ -153,7 +153,7 @@ namespace WinSW.Native
/// <exception cref="CommandException" />
internal Service OpenService(string serviceName, ServiceAccess access = ServiceAccess.All)
{
IntPtr serviceHandle = ServiceApis.OpenService(this.handle, serviceName, access);
var serviceHandle = ServiceApis.OpenService(this.handle, serviceName, access);
if (serviceHandle == IntPtr.Zero)
{
Throw.Command.Win32Exception("Failed to open the service.");
@ -164,7 +164,7 @@ namespace WinSW.Native
internal bool ServiceExists(string serviceName)
{
IntPtr serviceHandle = ServiceApis.OpenService(this.handle, serviceName, ServiceAccess.All);
var serviceHandle = ServiceApis.OpenService(this.handle, serviceName, ServiceAccess.All);
if (serviceHandle == IntPtr.Zero)
{
return false;
@ -202,7 +202,7 @@ namespace WinSW.Native
0,
out int bytesNeeded);
IntPtr config = Marshal.AllocHGlobal(bytesNeeded);
var config = Marshal.AllocHGlobal(bytesNeeded);
try
{
if (!QueryServiceConfig(
@ -231,7 +231,7 @@ namespace WinSW.Native
if (!QueryServiceStatusEx(
this.handle,
ServiceStatusType.ProcessInfo,
out SERVICE_STATUS_PROCESS status,
out var status,
sizeof(SERVICE_STATUS_PROCESS),
out _))
{
@ -247,7 +247,7 @@ namespace WinSW.Native
{
get
{
if (!QueryServiceStatus(this.handle, out SERVICE_STATUS status))
if (!QueryServiceStatus(this.handle, out var status))
{
Throw.Command.Win32Exception("Failed to query service status.");
}
@ -282,7 +282,7 @@ namespace WinSW.Native
/// <exception cref="CommandException" />
internal void SetStatus(IntPtr statusHandle, ServiceControllerStatus state)
{
if (!QueryServiceStatus(this.handle, out SERVICE_STATUS status))
if (!QueryServiceStatus(this.handle, out var status))
{
Throw.Command.Win32Exception("Failed to query service status.");
}

View File

@ -199,7 +199,7 @@ namespace WinSW.Native
var serviceName = new ReadOnlySpan<char>(this.ServiceName, new ReadOnlySpan<char>(this.ServiceName, 256).IndexOf('\0'));
var displayName = new ReadOnlySpan<char>(this.DisplayName, new ReadOnlySpan<char>(this.DisplayName, 256).IndexOf('\0'));
#if NETCOREAPP
#if NET
return string.Concat(displayName, " (", serviceName, ")");
#else
return string.Concat(displayName.ToString(), " (", serviceName.ToString(), ")");

View File

@ -51,7 +51,7 @@ namespace WinSW.Native
internal static void Win32Exception(int error, string message)
{
Debug.Assert(error != 0);
Win32Exception inner = new Win32Exception(error);
var inner = new Win32Exception(error);
Debug.Assert(message.EndsWith("."));
throw new CommandException(message + ' ' + inner.Message, inner);
}
@ -61,7 +61,7 @@ namespace WinSW.Native
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void Win32Exception()
{
Win32Exception inner = new Win32Exception();
var inner = new Win32Exception();
Debug.Assert(inner.NativeErrorCode != 0);
throw new CommandException(inner);
}
@ -70,7 +70,7 @@ namespace WinSW.Native
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void Win32Exception(string message)
{
Win32Exception inner = new Win32Exception();
var inner = new Win32Exception();
Debug.Assert(inner.NativeErrorCode != 0);
Debug.Assert(message.EndsWith("."));
throw new CommandException(message + ' ' + inner.Message, inner);

View File

@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#if !NETCOREAPP
#if !NET
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>

View File

@ -40,15 +40,15 @@ namespace WinSW
private PeriodicityType DeterminePeriodicityType()
{
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
DateTime epoch = new DateTime(1970, 1, 1);
var periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
var epoch = new DateTime(1970, 1, 1);
foreach (PeriodicityType i in ValidOrderedList)
foreach (var i in ValidOrderedList)
{
string r0 = epoch.ToString(this.format);
periodicRollingCalendar.Periodicity = i;
DateTime next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
var next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
string r1 = next.ToString(this.format);
if (r0 != r1)
@ -91,7 +91,7 @@ namespace WinSW
{
get
{
DateTime now = DateTime.Now;
var now = DateTime.Now;
if (now > this.nextRoll)
{
this.currentRoll = now;

View File

@ -1,8 +1,8 @@
#if !NETCOREAPP
#if !NET
using System;
#endif
using System.IO;
#if !NETCOREAPP
#if !NET
using System.Runtime.InteropServices;
#endif
@ -12,7 +12,7 @@ namespace WinSW.Util
{
public static void MoveOrReplaceFile(string sourceFileName, string destFileName)
{
#if NETCOREAPP
#if NET
File.Move(sourceFileName, destFileName, true);
#else
string sourceFilePath = Path.GetFullPath(sourceFileName);
@ -24,7 +24,7 @@ namespace WinSW.Util
}
#endif
}
#if !NETCOREAPP
#if !NET
private static Exception GetExceptionForLastWin32Error(string path) => Marshal.GetLastWin32Error() switch
{

View File

@ -18,7 +18,7 @@ namespace WinSW.Util
{
StopPrivate(process, millisecondsTimeout);
foreach (Process child in GetChildren(process))
foreach (var child in GetChildren(process))
{
using (child)
{
@ -29,7 +29,7 @@ namespace WinSW.Util
internal static void StopDescendants(this Process process, int millisecondsTimeout)
{
foreach (Process child in GetChildren(process))
foreach (var child in GetChildren(process))
{
using (child)
{
@ -40,12 +40,12 @@ namespace WinSW.Util
internal static unsafe List<Process> GetChildren(this Process process)
{
DateTime startTime = process.StartTime;
var startTime = process.StartTime;
int processId = process.Id;
var children = new List<Process>();
foreach (Process other in Process.GetProcesses())
foreach (var other in Process.GetProcesses())
{
try
{
@ -54,12 +54,12 @@ namespace WinSW.Util
goto Next;
}
IntPtr handle = other.Handle;
var handle = other.Handle;
if (NtQueryInformationProcess(
handle,
PROCESSINFOCLASS.ProcessBasicInformation,
out PROCESS_BASIC_INFORMATION information,
out var information,
sizeof(PROCESS_BASIC_INFORMATION)) != 0)
{
goto Next;
@ -119,7 +119,7 @@ namespace WinSW.Util
}
}
#if NETCOREAPP
#if NET
process.Kill();
#else
try
@ -169,7 +169,7 @@ namespace WinSW.Util
}
}
#if NETCOREAPP
#if NET
process.Kill();
#else
try

View File

@ -10,7 +10,7 @@ namespace WinSW.Util
/// <exception cref="CommandException" />
internal static unsafe DateTime GetLastWriteTime(this RegistryKey registryKey)
{
int error = RegQueryInfoKeyW(registryKey.Handle, null, null, null, null, null, null, null, null, null, null, out FILETIME lastWriteTime);
int error = RegQueryInfoKeyW(registryKey.Handle, null, null, null, null, null, null, null, null, null, null, out var lastWriteTime);
if (error != Errors.ERROR_SUCCESS)
{
Throw.Command.Win32Exception(error, "Failed to query registry key.");

View File

@ -17,7 +17,7 @@ namespace WinSW.Util
/// <exception cref="InvalidDataException">The required element is missing</exception>
public static string? SingleElement(XmlNode node, string tagName, bool optional)
{
XmlNode? n = node.SelectSingleNode(tagName);
var n = node.SelectSingleNode(tagName);
if (n is null && !optional)
{
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
@ -36,7 +36,7 @@ namespace WinSW.Util
/// <exception cref="InvalidDataException">The required element is missing</exception>
public static XmlNode? SingleNode(XmlNode node, string tagName, bool optional)
{
XmlNode? n = node.SelectSingleNode(tagName);
var n = node.SelectSingleNode(tagName);
if (n is null && !optional)
{
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");

View File

@ -23,13 +23,13 @@ namespace WinSW.Plugins.SharedDirectoryMapper
public SharedDirectoryMapper(bool enableMapping, string directoryUNC, string driveLabel)
{
SharedDirectoryMapperConfig config = new SharedDirectoryMapperConfig(enableMapping, driveLabel, directoryUNC);
var config = new SharedDirectoryMapperConfig(enableMapping, driveLabel, directoryUNC);
this.entries.Add(config);
}
public override void Configure(XmlServiceConfig config, XmlNode node)
{
XmlNodeList? mapNodes = XmlHelper.SingleNode(node, "mapping", false)!.SelectNodes("map");
var mapNodes = XmlHelper.SingleNode(node, "mapping", false)!.SelectNodes("map");
if (mapNodes != null)
{
for (int i = 0; i < mapNodes.Count; i++)
@ -44,7 +44,7 @@ namespace WinSW.Plugins.SharedDirectoryMapper
public override void OnWrapperStarted()
{
foreach (SharedDirectoryMapperConfig config in this.entries)
foreach (var 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 (var config in this.entries)
{
string label = config.Label;
if (config.EnableMapping)
@ -88,7 +88,7 @@ namespace WinSW.Plugins.SharedDirectoryMapper
private void ThrowExtensionException(int error, string message)
{
Win32Exception inner = new Win32Exception(error);
var inner = new Win32Exception(error);
throw new ExtensionException(this.Descriptor.Id, $"{this.DisplayName}: {message} {inner.Message}", inner);
}

View File

@ -75,7 +75,7 @@ namespace WinSW.Tests
{
const string commandName = "unknown";
CommandLineTestResult result = Helper.ErrorTest(new[] { commandName });
var result = Helper.ErrorTest(new[] { commandName });
Assert.Equal($"Unrecognized command or argument '{commandName}'\r\n\r\n", result.Error);
}
@ -101,7 +101,7 @@ namespace WinSW.Tests
Assert.Equal(OldCompanyName, FileVersionInfo.GetVersionInfo(inputPath).CompanyName);
// deny write access
using FileStream file = File.OpenRead(inputPath);
using var file = File.OpenRead(inputPath);
string outputPath = Path.GetTempFileName();
Program.TestExecutablePath = inputPath;

View File

@ -1,5 +1,4 @@
using System;
using System.IO;
using System.IO;
using System.Xml;
using WinSW.Tests.Util;
using Xunit;
@ -15,7 +14,7 @@ namespace WinSW.Tests.Configuration
[Fact]
public void AllOptionsConfigShouldDeclareDefaults()
{
XmlServiceConfig config = Load("complete");
var config = Load("complete");
Assert.Equal("myapp", config.Name);
Assert.Equal("%BASE%\\myExecutable.exe", config.Executable);
@ -26,7 +25,7 @@ namespace WinSW.Tests.Configuration
[Fact]
public void MinimalConfigShouldDeclareDefaults()
{
XmlServiceConfig config = Load("minimal");
var config = Load("minimal");
Assert.Equal("myapp", config.Name);
Assert.Equal("%BASE%\\myExecutable.exe", config.Executable);
@ -41,7 +40,7 @@ namespace WinSW.Tests.Configuration
string path = Path.Combine(directory, $@"samples\sample-{exampleName}.xml");
Assert.True(File.Exists(path));
XmlDocument dom = new XmlDocument();
var dom = new XmlDocument();
dom.Load(path);
return new XmlServiceConfig(dom);
}

View File

@ -21,7 +21,7 @@ namespace WinSW.Tests
public void Roundtrip_Defaults()
{
// Roundtrip data
Download d = new Download(From, To);
var d = new Download(From, To);
var config = ConfigXmlBuilder.Create(this.output)
.WithDownload(d)
.ToServiceConfig(true);
@ -39,7 +39,7 @@ namespace WinSW.Tests
public void Roundtrip_BasicAuth()
{
// Roundtrip data
Download d = new Download(From, To, true, Download.AuthType.Basic, "aUser", "aPassword", true);
var d = new Download(From, To, true, Download.AuthType.Basic, "aUser", "aPassword", true);
var config = ConfigXmlBuilder.Create(this.output)
.WithDownload(d)
.ToServiceConfig(true);
@ -57,7 +57,7 @@ namespace WinSW.Tests
public void Roundtrip_SSPI()
{
// Roundtrip data
Download d = new Download(From, To, false, Download.AuthType.Sspi);
var d = new Download(From, To, false, Download.AuthType.Sspi);
var config = ConfigXmlBuilder.Create(this.output)
.WithDownload(d)
.ToServiceConfig(true);
@ -105,7 +105,7 @@ namespace WinSW.Tests
[InlineData(false)]
public void Download_FailOnError(bool failOnError)
{
Download d = new Download(From, To, failOnError);
var d = new Download(From, To, failOnError);
var config = ConfigXmlBuilder.Create(this.output)
.WithDownload(d)

View File

@ -19,7 +19,7 @@ namespace WinSW.Tests
public DownloadTests()
{
TcpListener tcpListener = new TcpListener(IPAddress.Loopback, 0);
var tcpListener = new TcpListener(IPAddress.Loopback, 0);
tcpListener.Start();
int port = ((IPEndPoint)tcpListener.LocalEndpoint).Port;
string prefix = $"http://localhost:{port}/";
@ -39,7 +39,7 @@ namespace WinSW.Tests
private async Task TestClientServerAsync(Func<string, string, Task> client, Action<HttpListenerContext> server, AuthenticationSchemes authenticationSchemes = AuthenticationSchemes.Anonymous, [CallerMemberName] string path = null)
{
HttpListener listener = new HttpListener();
var listener = new HttpListener();
string prefix = $"{this.globalPrefix}{path}/";
listener.Prefixes.Add(prefix);
listener.AuthenticationSchemes = authenticationSchemes;
@ -72,7 +72,7 @@ namespace WinSW.Tests
async Task ListenAsync()
{
HttpListenerContext context = await listener.GetContextAsync();
var context = await listener.GetContextAsync();
try
{
server(context);
@ -136,7 +136,7 @@ namespace WinSW.Tests
},
context =>
{
HttpListenerBasicIdentity identity = (HttpListenerBasicIdentity)context.User.Identity;
var identity = (HttpListenerBasicIdentity)context.User.Identity;
if (identity.Name != username || identity.Password != password)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
@ -152,8 +152,8 @@ namespace WinSW.Tests
[Fact]
public async Task TestHttp_IfModifiedSince_ModifiedAsync()
{
DateTime lastModified = DateTime.Now.TrimToSeconds();
DateTime prevModified = lastModified.AddDays(-1);
var lastModified = DateTime.Now.TrimToSeconds();
var prevModified = lastModified.AddDays(-1);
await this.TestClientServerAsync(
async (source, dest) =>
@ -180,7 +180,7 @@ namespace WinSW.Tests
[Fact]
public async Task TestHttp_IfModifiedSince_NotModifiedAsync()
{
DateTime lastModified = DateTime.Now.TrimToSeconds();
var lastModified = DateTime.Now.TrimToSeconds();
await this.TestClientServerAsync(
async (source, dest) =>
@ -210,7 +210,7 @@ namespace WinSW.Tests
await this.TestClientServerAsync(
async (source, dest) =>
{
WebException exception = await Assert.ThrowsAsync<WebException>(
var exception = await Assert.ThrowsAsync<WebException>(
async () => await new Download(source, dest).PerformAsync());
Assert.Equal(WebExceptionStatus.ProtocolError, exception.Status);

View File

@ -41,7 +41,7 @@ $@"<service>
[Fact]
public void LoadExtensions()
{
WinSWExtensionManager manager = new WinSWExtensionManager(this.serviceConfig);
var manager = new WinSWExtensionManager(this.serviceConfig);
manager.LoadExtensions();
Assert.Equal(2, manager.Extensions.Count);
}
@ -49,7 +49,7 @@ $@"<service>
[Fact]
public void StartStopExtension()
{
WinSWExtensionManager manager = new WinSWExtensionManager(this.serviceConfig);
var manager = new WinSWExtensionManager(this.serviceConfig);
manager.LoadExtensions();
manager.FireOnWrapperStarted();
manager.FireBeforeWrapperStopped();

View File

@ -1,4 +1,4 @@
#if NETCOREAPP
#if NET
using System;
using System.IO;
using System.Runtime.CompilerServices;
@ -14,10 +14,10 @@ namespace WinSW.Tests.Extensions
[ElevatedFact]
public void TestMap()
{
using TestData data = TestData.Create();
using var data = TestData.Create();
const string label = "W:";
SharedDirectoryMapper mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}", label);
var mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}", label);
mapper.OnWrapperStarted();
Assert.True(Directory.Exists($@"{label}\"));
@ -28,10 +28,10 @@ namespace WinSW.Tests.Extensions
[ElevatedFact]
public void TestDisableMapping()
{
using TestData data = TestData.Create();
using var data = TestData.Create();
const string label = "W:";
SharedDirectoryMapper mapper = new SharedDirectoryMapper(enableMapping: false, $@"\\{Environment.MachineName}\{data.name}", label);
var mapper = new SharedDirectoryMapper(enableMapping: false, $@"\\{Environment.MachineName}\{data.name}", label);
mapper.OnWrapperStarted();
Assert.False(Directory.Exists($@"{label}\"));
@ -41,10 +41,10 @@ namespace WinSW.Tests.Extensions
[ElevatedFact]
public void TestMap_PathEndsWithSlash_Throws()
{
using TestData data = TestData.Create();
using var data = TestData.Create();
const string label = "W:";
SharedDirectoryMapper mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}\", label);
var mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}\", label);
_ = Assert.ThrowsAny<Exception>(() => mapper.OnWrapperStarted());
Assert.False(Directory.Exists($@"{label}\"));
@ -54,10 +54,10 @@ namespace WinSW.Tests.Extensions
[ElevatedFact]
public void TestMap_LabelDoesNotEndWithColon_Throws()
{
using TestData data = TestData.Create();
using var data = TestData.Create();
const string label = "W";
SharedDirectoryMapper mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}", label);
var mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}", label);
_ = Assert.ThrowsAny<Exception>(() => mapper.OnWrapperStarted());
Assert.False(Directory.Exists($@"{label}\"));
@ -82,7 +82,7 @@ namespace WinSW.Tests.Extensions
try
{
NativeMethods.SHARE_INFO_2 shareInfo = new NativeMethods.SHARE_INFO_2
var shareInfo = new NativeMethods.SHARE_INFO_2
{
netname = name,
type = NativeMethods.STYPE_DISKTREE | NativeMethods.STYPE_TEMPORARY,

View File

@ -405,7 +405,7 @@ $@"<service>
<arguments>arguments</arguments>
</service>";
XmlServiceConfig config = XmlServiceConfig.FromXml(seedXml);
var config = XmlServiceConfig.FromXml(seedXml);
VerifyEqual(prestart, config.Prestart);
VerifyEqual(poststart, config.Poststart);

View File

@ -33,11 +33,11 @@ $@"<service>
/// <exception cref="Exception">Command failure</exception>
public static string Test(string[] arguments, XmlServiceConfig config = null)
{
TextWriter tmpOut = Console.Out;
TextWriter tmpError = Console.Error;
var tmpOut = Console.Out;
var tmpError = Console.Error;
using StringWriter swOut = new StringWriter();
using StringWriter swError = new StringWriter();
using var swOut = new StringWriter();
using var swError = new StringWriter();
Console.SetOut(swOut);
Console.SetError(swError);
@ -67,11 +67,11 @@ $@"<service>
{
Exception exception = null;
TextWriter tmpOut = Console.Out;
TextWriter tmpError = Console.Error;
var tmpOut = Console.Out;
var tmpError = Console.Error;
using StringWriter swOut = new StringWriter();
using StringWriter swError = new StringWriter();
using var swOut = new StringWriter();
using var swError = new StringWriter();
Console.SetOut(swOut);
Console.SetError(swError);

View File

@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Text;
using WinSW.Tests.Extensions;
using Xunit.Abstractions;
namespace WinSW.Tests.Util
@ -57,7 +56,7 @@ namespace WinSW.Tests.Util
public string ToXmlString(bool dumpConfig = false)
{
StringBuilder str = new StringBuilder();
var str = new StringBuilder();
if (this.PrintXmlVersion)
{
// TODO: The encoding is generally wrong
@ -121,7 +120,7 @@ namespace WinSW.Tests.Util
public ConfigXmlBuilder WithDownload(Download download)
{
StringBuilder xml = new StringBuilder();
var xml = new StringBuilder();
xml.Append($"<download from=\"{download.From}\" to=\"{download.To}\" failOnError=\"{download.FailOnError}\"");
// Authentication

View File

@ -48,7 +48,7 @@ namespace WinSW.Tests.Util
hr = client.SetEventCallbacks(this);
AssertEx.Succeeded(hr);
IntPtr pointer = Marshal.GetIUnknownForObject(client);
var pointer = Marshal.GetIUnknownForObject(client);
Assert.Equal(1, Marshal.Release(pointer));
target = DataTarget.CreateFromDbgEng(pointer);
@ -125,7 +125,7 @@ namespace WinSW.Tests.Util
{
using var runtime = this.target.ClrVersions.Single().CreateRuntime();
var module = runtime.EnumerateModules().First(module => module.Name == typeof(Program).Assembly.Location);
ClrModule module = runtime.EnumerateModules().First(module => module.Name == typeof(Program).Assembly.Location);
var type = module.GetTypeByName(this.trackerType.FullName);
var field = type.GetStaticFieldByName(this.hitsField.Name);

View File

@ -39,7 +39,7 @@ namespace WinSW.Tests.Util
internal static string NET461Exe => Path.Combine(ArtifactsDirectory, "publish", "WinSW.NET461.exe");
internal static string WinSWExe =>
#if NETCOREAPP
#if NET
Path.ChangeExtension(typeof(Program).Assembly.Location, ".exe");
#else
typeof(Program).Assembly.Location;

View File

@ -1,5 +1,4 @@
using System.Reflection;
using WinSW.Configuration;
using WinSW.Configuration;
using Xunit;
namespace WinSW.Tests.Util

View File

@ -19,7 +19,7 @@ namespace WinSW.Logging
protected override void Append(LoggingEvent loggingEvent)
{
IServiceEventLog? eventLog = this.provider.Locate();
var eventLog = this.provider.Locate();
// We write the event iff the provider is ready
eventLog?.WriteEntry(loggingEvent.RenderedMessage, ToEventLogEntryType(loggingEvent.Level));

View File

@ -10,7 +10,7 @@ namespace WinSW.Logging
{
Console.ResetColor();
Level level = loggingEvent.Level;
var level = loggingEvent.Level;
Console.ForegroundColor =
level >= Level.Error ? ConsoleColor.Red :
level >= Level.Warn ? ConsoleColor.Yellow :

View File

@ -51,7 +51,7 @@ namespace WinSW
return TestExecutablePath;
}
using Process current = Process.GetCurrentProcess();
using var current = Process.GetCurrentProcess();
return current.MainModule!.FileName!;
}
}
@ -90,7 +90,7 @@ namespace WinSW
Console.SetError(new StreamWriter(stderr) { AutoFlush = true });
}
#if NETCOREAPP
#if NET
args = args[4..];
#else
string[] oldArgs = args;
@ -116,15 +116,13 @@ namespace WinSW
XmlServiceConfig config = null!;
try
{
config = LoadConfig(pathToConfig);
config = LoadConfigAndInitLoggers(pathToConfig, false);
}
catch (FileNotFoundException)
{
Throw.Command.Exception("The specified command or file was not found.");
}
InitLoggers(config, enableConsoleLogging: false);
Log.Debug("Starting WinSW in service mode.");
AutoRefresh(config);
@ -141,9 +139,9 @@ namespace WinSW
}),
};
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
using (var identity = WindowsIdentity.GetCurrent())
{
WindowsPrincipal principal = new WindowsPrincipal(identity);
var principal = new WindowsPrincipal(identity);
if (principal.IsInRole(new SecurityIdentifier(WellKnownSidType.ServiceSid, null)) ||
principal.IsInRole(new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null)) ||
principal.IsInRole(new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null)) ||
@ -420,8 +418,7 @@ namespace WinSW
void Install(string? pathToConfig, bool noElevate, string? username, string? password)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
InitLoggers(config, enableConsoleLogging: true);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
if (!elevated)
{
@ -431,7 +428,7 @@ namespace WinSW
Log.Info($"Installing service '{config.Format()}'...");
using ServiceManager scm = ServiceManager.Open(ServiceManagerAccess.CreateService);
using var scm = ServiceManager.Open(ServiceManagerAccess.CreateService);
if (scm.ServiceExists(config.Name))
{
@ -468,7 +465,7 @@ namespace WinSW
Security.AddServiceLogonRight(ref username);
}
using Service sc = scm.CreateService(
using var sc = scm.CreateService(
config.Name,
config.DisplayName,
config.StartMode,
@ -483,7 +480,7 @@ namespace WinSW
sc.SetDescription(description);
}
SC_ACTION[] actions = config.FailureActions;
var actions = config.FailureActions;
if (actions.Length > 0)
{
sc.SetFailureActions(config.ResetFailureAfter, actions);
@ -545,8 +542,7 @@ namespace WinSW
void Uninstall(string? pathToConfig, bool noElevate)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
InitLoggers(config, enableConsoleLogging: true);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
if (!elevated)
{
@ -556,10 +552,10 @@ namespace WinSW
Log.Info($"Uninstalling service '{config.Format()}'...");
using ServiceManager scm = ServiceManager.Open(ServiceManagerAccess.Connect);
using var scm = ServiceManager.Open(ServiceManagerAccess.Connect);
try
{
using Service sc = scm.OpenService(config.Name);
using var sc = scm.OpenService(config.Name);
if (sc.Status != ServiceControllerStatus.Stopped)
{
@ -595,8 +591,7 @@ namespace WinSW
void Start(string? pathToConfig, bool noElevate, bool noWait, CancellationToken ct)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
InitLoggers(config, enableConsoleLogging: true);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
if (!elevated)
{
@ -641,8 +636,7 @@ namespace WinSW
void Stop(string? pathToConfig, bool noElevate, bool noWait, bool force, CancellationToken ct)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
InitLoggers(config, enableConsoleLogging: true);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
if (!elevated)
{
@ -695,8 +689,7 @@ namespace WinSW
void Restart(string? pathToConfig, bool noElevate, bool force, CancellationToken ct)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
InitLoggers(config, enableConsoleLogging: true);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
if (!elevated)
{
@ -758,7 +751,7 @@ namespace WinSW
if (startedDependentServices != null)
{
foreach (ServiceController service in startedDependentServices)
foreach (var service in startedDependentServices)
{
if (service.Status == ServiceControllerStatus.Stopped)
{
@ -773,8 +766,7 @@ namespace WinSW
void RestartSelf(string? pathToConfig)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
InitLoggers(config, enableConsoleLogging: true);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
if (!elevated)
{
@ -794,7 +786,7 @@ namespace WinSW
IntPtr.Zero,
null,
default,
out ProcessApis.PROCESS_INFORMATION processInfo))
out var processInfo))
{
Throw.Command.Win32Exception("Failed to invoke restart.");
}
@ -805,8 +797,7 @@ namespace WinSW
static int Status(string? pathToConfig)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
InitLoggers(config, enableConsoleLogging: true);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
using var svc = new ServiceController(config.Name);
try
@ -838,8 +829,7 @@ namespace WinSW
void Test(string? pathToConfig, bool noElevate, bool noBreak)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
InitLoggers(config, enableConsoleLogging: true);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
if (!elevated)
{
@ -849,7 +839,7 @@ namespace WinSW
AutoRefresh(config);
using WrapperService wsvc = new WrapperService(config);
using var wsvc = new WrapperService(config);
wsvc.RaiseOnStart(args);
try
{
@ -860,7 +850,7 @@ namespace WinSW
}
else
{
using ManualResetEvent evt = new ManualResetEvent(false);
using var evt = new ManualResetEvent(false);
Console.WriteLine("Press Ctrl+C to stop the service...");
Console.CancelKeyPress += CancelKeyPress;
@ -883,8 +873,7 @@ namespace WinSW
void Refresh(string? pathToConfig, bool noElevate)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
InitLoggers(config, enableConsoleLogging: true);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
if (!elevated)
{
@ -900,7 +889,7 @@ namespace WinSW
if (all)
{
using var scm = ServiceManager.Open(ServiceManagerAccess.EnumerateService);
(IntPtr services, int count) = scm.EnumerateServices();
(var services, int count) = scm.EnumerateServices();
try
{
int prevProcessId = -1;
@ -915,7 +904,7 @@ namespace WinSW
{
if (prevProcessId >= 0)
{
using Process process = Process.GetProcessById(prevProcessId);
using var process = Process.GetProcessById(prevProcessId);
Draw(process, string.Empty, false);
}
}
@ -926,7 +915,7 @@ namespace WinSW
if (prevProcessId >= 0)
{
using Process process = Process.GetProcessById(prevProcessId);
using var process = Process.GetProcessById(prevProcessId);
Draw(process, string.Empty, true);
}
}
@ -937,15 +926,15 @@ namespace WinSW
}
else
{
XmlServiceConfig config = LoadConfig(pathToConfig);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
using ServiceManager scm = ServiceManager.Open(ServiceManagerAccess.Connect);
using Service sc = scm.OpenService(config.Name, ServiceAccess.QueryStatus);
using var scm = ServiceManager.Open(ServiceManagerAccess.Connect);
using var sc = scm.OpenService(config.Name, ServiceAccess.QueryStatus);
int processId = sc.ProcessId;
if (processId >= 0)
{
using Process process = Process.GetProcessById(processId);
using var process = Process.GetProcessById(processId);
Draw(process, string.Empty, true);
}
}
@ -972,11 +961,11 @@ namespace WinSW
Console.WriteLine(process.Format());
List<Process> children = process.GetChildren();
var children = process.GetChildren();
int count = children.Count;
for (int i = 0; i < count; i++)
{
using Process child = children[i];
using var child = children[i];
Draw(child, indentation, i == count - 1);
}
}
@ -984,7 +973,7 @@ namespace WinSW
void DevKill(string? pathToConfig, bool noElevate)
{
XmlServiceConfig config = LoadConfig(pathToConfig);
var config = LoadConfigAndInitLoggers(pathToConfig, true);
if (!elevated)
{
@ -992,13 +981,13 @@ namespace WinSW
return;
}
using ServiceManager scm = ServiceManager.Open();
using Service sc = scm.OpenService(config.Name);
using var scm = ServiceManager.Open();
using var sc = scm.OpenService(config.Name);
int processId = sc.ProcessId;
if (processId >= 0)
{
using Process process = Process.GetProcessById(processId);
using var process = Process.GetProcessById(processId);
process.StopDescendants(config.StopTimeoutInMs);
}
@ -1007,7 +996,7 @@ namespace WinSW
static unsafe void DevList()
{
using var scm = ServiceManager.Open(ServiceManagerAccess.EnumerateService);
(IntPtr services, int count) = scm.EnumerateServices();
(var services, int count) = scm.EnumerateServices();
try
{
for (int i = 0; i < count; i++)
@ -1058,7 +1047,7 @@ namespace WinSW
" " + (stderrName ?? NoPipe) +
commandLine.Remove(commandLine.IndexOf(exe), exe.Length).TrimStart('"');
ProcessStartInfo startInfo = new ProcessStartInfo
var startInfo = new ProcessStartInfo
{
UseShellExecute = true,
Verb = "runas",
@ -1069,7 +1058,7 @@ namespace WinSW
try
{
using Process elevated = Process.Start(startInfo)!;
using var elevated = Process.Start(startInfo)!;
if (stdinName is not null)
{
@ -1106,9 +1095,9 @@ namespace WinSW
return;
}
DateTime fileLastWriteTime = File.GetLastWriteTime(config.FullPath);
var fileLastWriteTime = File.GetLastWriteTime(config.FullPath);
using RegistryKey? registryKey = Registry.LocalMachine
using var registryKey = Registry.LocalMachine
.OpenSubKey("SYSTEM")?
.OpenSubKey("CurrentControlSet")?
.OpenSubKey("Services")?
@ -1119,7 +1108,7 @@ namespace WinSW
return;
}
DateTime registryLastWriteTime = registryKey.GetLastWriteTime();
var registryLastWriteTime = registryKey.GetLastWriteTime();
if (fileLastWriteTime > registryLastWriteTime)
{
@ -1129,16 +1118,16 @@ namespace WinSW
static void DoRefresh(XmlServiceConfig config)
{
using ServiceManager scm = ServiceManager.Open(ServiceManagerAccess.Connect);
using var scm = ServiceManager.Open(ServiceManagerAccess.Connect);
try
{
using Service sc = scm.OpenService(config.Name);
using var sc = scm.OpenService(config.Name);
sc.ChangeConfig(config.DisplayName, config.StartMode, config.ServiceDependencies);
sc.SetDescription(config.Description);
SC_ACTION[] actions = config.FailureActions;
var actions = config.FailureActions;
if (actions.Length > 0)
{
sc.SetFailureActions(config.ResetFailureAfter, actions);
@ -1173,43 +1162,55 @@ namespace WinSW
}
/// <exception cref="FileNotFoundException" />
private static XmlServiceConfig LoadConfig(string? path)
private static XmlServiceConfig LoadConfigAndInitLoggers(string? path, bool enableConsoleLogging)
{
if (TestConfig != null)
{
return TestConfig;
}
if (path != null)
// TODO: Make logging levels configurable
var fileLogLevel = Level.Debug;
// TODO: Debug should not be printed to console by default. Otherwise commands like 'status' will be pollutted
// This is a workaround till there is a better command line parsing, which will allow determining
var consoleLogLevel = Level.Info;
var eventLogLevel = Level.Warn;
// console log
if (enableConsoleLogging)
{
return new XmlServiceConfig(path);
var consoleAppender = new WinSWConsoleAppender
{
Name = "Wrapper console log",
Threshold = consoleLogLevel,
Layout = new PatternLayout("%date{ABSOLUTE} - %message%newline"),
};
consoleAppender.ActivateOptions();
BasicConfigurator.Configure(
#if NET
LogManager.GetRepository(Assembly.GetExecutingAssembly()),
#endif
consoleAppender);
}
XmlServiceConfig config;
if (path != null)
{
config = new XmlServiceConfig(path);
}
else
{
path = Path.ChangeExtension(ExecutablePath, ".xml");
if (!File.Exists(path))
{
throw new FileNotFoundException("Unable to locate " + Path.GetFileNameWithoutExtension(path) + ".xml file within executable directory.");
}
return new XmlServiceConfig(path);
config = new XmlServiceConfig(path);
}
private static void InitLoggers(XmlServiceConfig config, bool enableConsoleLogging)
{
if (XmlServiceConfig.TestConfig != null)
{
return;
}
// TODO: Make logging levels configurable
Level fileLogLevel = Level.Debug;
// TODO: Debug should not be printed to console by default. Otherwise commands like 'status' will be pollutted
// This is a workaround till there is a better command line parsing, which will allow determining
Level consoleLogLevel = Level.Info;
Level eventLogLevel = Level.Warn;
List<IAppender> appenders = new List<IAppender>();
// .wrapper.log
string wrapperLogPath = Path.Combine(config.LogDirectory, config.BaseName + ".wrapper.log");
var wrapperLog = new FileAppender
@ -1223,20 +1224,6 @@ namespace WinSW
Layout = new PatternLayout("%date %-5level - %message%newline"),
};
wrapperLog.ActivateOptions();
appenders.Add(wrapperLog);
// console log
if (enableConsoleLogging)
{
var consoleAppender = new WinSWConsoleAppender
{
Name = "Wrapper console log",
Threshold = consoleLogLevel,
Layout = new PatternLayout("%date{ABSOLUTE} - %message%newline"),
};
consoleAppender.ActivateOptions();
appenders.Add(consoleAppender);
}
// event log
var systemEventLogger = new ServiceEventLogAppender(WrapperService.eventLogProvider)
@ -1245,20 +1232,22 @@ namespace WinSW
Threshold = eventLogLevel,
};
systemEventLogger.ActivateOptions();
appenders.Add(systemEventLogger);
BasicConfigurator.Configure(
#if NETCOREAPP
LogManager.GetRepository(System.Reflection.Assembly.GetExecutingAssembly()),
#if NET
LogManager.GetRepository(Assembly.GetExecutingAssembly()),
#endif
appenders.ToArray());
wrapperLog,
systemEventLogger);
return config;
}
/// <exception cref="CommandException" />
internal static bool IsProcessElevated()
{
IntPtr process = ProcessApis.GetCurrentProcess();
if (!ProcessApis.OpenProcessToken(process, TokenAccessLevels.Read, out IntPtr token))
var process = ProcessApis.GetCurrentProcess();
if (!ProcessApis.OpenProcessToken(process, TokenAccessLevels.Read, out var token))
{
Throw.Command.Win32Exception("Failed to open process token.");
}
@ -1270,7 +1259,7 @@ namespace WinSW
if (!SecurityApis.GetTokenInformation(
token,
SecurityApis.TOKEN_INFORMATION_CLASS.TokenElevation,
out SecurityApis.TOKEN_ELEVATION elevation,
out var elevation,
sizeof(SecurityApis.TOKEN_ELEVATION),
out _))
{
@ -1288,10 +1277,10 @@ namespace WinSW
private static string ReadPassword()
{
StringBuilder buf = new StringBuilder();
var buf = new StringBuilder();
while (true)
{
ConsoleKeyInfo key = Console.ReadKey(true);
var key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter)
{
return buf.ToString();

View File

@ -11,7 +11,7 @@ namespace WinSW
/// <exception cref="TimeoutException" />
internal static void WaitForStatus(this ServiceController serviceController, ServiceControllerStatus desiredStatus, ServiceControllerStatus pendingStatus, CancellationToken ct)
{
TimeSpan timeout = new TimeSpan(TimeSpan.TicksPerSecond);
var timeout = new TimeSpan(TimeSpan.TicksPerSecond);
for (; ; )
{
try

View File

@ -22,7 +22,7 @@ namespace WinSW
private static readonly int additionalStopTimeout = 1_000;
private static readonly ILog Log = LogManager.GetLogger(
#if NETCOREAPP
#if NET
Assembly.GetExecutingAssembly(),
#endif
"WinSW");
@ -71,7 +71,7 @@ namespace WinSW
/// </summary>
private void HandleFileCopies()
{
var file = this.config.BasePath + ".copies";
string? file = this.config.BasePath + ".copies";
if (!File.Exists(file))
{
return; // nothing to handle
@ -128,7 +128,7 @@ namespace WinSW
Directory.CreateDirectory(logDirectory);
}
LogHandler logAppender = this.config.LogHandler;
var logAppender = this.config.LogHandler;
logAppender.EventLogger = this;
return logAppender;
}
@ -264,11 +264,11 @@ namespace WinSW
this.HandleFileCopies();
// handle downloads
List<Download> downloads = this.config.Downloads;
Task[] tasks = new Task[downloads.Count];
var downloads = this.config.Downloads;
var tasks = new Task[downloads.Count];
for (int i = 0; i < downloads.Count; i++)
{
Download download = downloads[i];
var download = downloads[i];
string downloadMessage = $"Downloading: {download.From} to {download.To}. failOnError={download.FailOnError.ToString()}";
Log.Info(downloadMessage);
tasks[i] = download.PerformAsync();
@ -280,14 +280,14 @@ namespace WinSW
}
catch (AggregateException e)
{
List<Exception> exceptions = new List<Exception>(e.InnerExceptions.Count);
var exceptions = new List<Exception>(e.InnerExceptions.Count);
for (int i = 0; i < tasks.Length; i++)
{
if (tasks[i].IsFaulted)
{
Download download = downloads[i];
var download = downloads[i];
string errorMessage = $"Failed to download {download.From} to {download.To}";
AggregateException exception = tasks[i].Exception!;
var exception = tasks[i].Exception!;
Log.Error(errorMessage, exception);
// TODO: move this code into the download logic
@ -301,13 +301,13 @@ namespace WinSW
throw new AggregateException(exceptions);
}
ProcessCommand prestart = this.config.Prestart;
var prestart = this.config.Prestart;
string? prestartExecutable = prestart.Executable;
if (prestartExecutable != null)
{
try
{
using Process process = this.StartProcess(prestartExecutable, prestart.Arguments, prestart.CreateLogHandler());
using var process = this.StartProcess(prestartExecutable, prestart.Arguments, prestart.CreateLogHandler());
this.WaitForProcessToExit(process);
this.LogExited($"Pre-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
process.StopDescendants(additionalStopTimeout);
@ -326,17 +326,17 @@ namespace WinSW
this.ExtensionManager.LoadExtensions();
this.ExtensionManager.FireOnWrapperStarted();
LogHandler executableLogHandler = this.CreateExecutableLogHandler();
var executableLogHandler = this.CreateExecutableLogHandler();
this.process = this.StartProcess(this.config.Executable, startArguments, executableLogHandler, this.OnMainProcessExited);
this.ExtensionManager.FireOnProcessStarted(this.process);
ProcessCommand poststart = this.config.Poststart;
var poststart = this.config.Poststart;
string? poststartExecutable = poststart.Executable;
if (poststartExecutable != null)
{
try
{
using Process process = StartProcessLocked();
using var process = StartProcessLocked();
this.WaitForProcessToExit(process);
this.LogExited($"Post-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
process.StopDescendants(additionalStopTimeout);
@ -362,13 +362,13 @@ namespace WinSW
/// </summary>
private void DoStop()
{
ProcessCommand prestop = this.config.Prestop;
var prestop = this.config.Prestop;
string? prestopExecutable = prestop.Executable;
if (prestopExecutable != null)
{
try
{
using Process process = StartProcessLocked(prestopExecutable, prestop.Arguments, prestop.CreateLogHandler());
using var process = StartProcessLocked(prestopExecutable, prestop.Arguments, prestop.CreateLogHandler());
this.WaitForProcessToExit(process);
this.LogExited($"Pre-stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
process.StopDescendants(additionalStopTimeout);
@ -387,7 +387,7 @@ namespace WinSW
string? stopArguments = this.config.StopArguments;
if (stopExecutable is null && stopArguments is null)
{
Process process = this.process;
var process = this.process;
Log.Debug("ProcessKill " + process.Id);
bool? result = process.Stop(this.config.StopTimeoutInMs);
this.LogMinimal($"Child process '{process.Format()}' " + result switch
@ -408,7 +408,7 @@ namespace WinSW
try
{
// TODO: Redirect logging to Log4Net once https://github.com/kohsuke/winsw/pull/213 is integrated
using Process stopProcess = StartProcessLocked(stopExecutable, stopArguments);
using var stopProcess = StartProcessLocked(stopExecutable, stopArguments);
Log.Debug("WaitForProcessToExit " + this.process.Id + "+" + stopProcess.Id);
this.WaitForProcessToExit(stopProcess);
@ -425,13 +425,13 @@ namespace WinSW
}
}
ProcessCommand poststop = this.config.Poststop;
var poststop = this.config.Poststop;
string? poststopExecutable = poststop.Executable;
if (poststopExecutable != null)
{
try
{
using Process process = StartProcessLocked(poststopExecutable, poststop.Arguments, poststop.CreateLogHandler());
using var process = StartProcessLocked(poststopExecutable, poststop.Arguments, poststop.CreateLogHandler());
this.WaitForProcessToExit(process);
this.LogExited($"Post-Stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
process.StopDescendants(additionalStopTimeout);
@ -477,13 +477,13 @@ namespace WinSW
private void AcceptPreshutdown()
{
const string acceptedCommandsFieldName =
#if NETCOREAPP
#if NET
"_acceptedCommands";
#else
"acceptedCommands";
#endif
FieldInfo? acceptedCommandsField = typeof(ServiceBase).GetField(acceptedCommandsFieldName, BindingFlags.Instance | BindingFlags.NonPublic);
var acceptedCommandsField = typeof(ServiceBase).GetField(acceptedCommandsFieldName, BindingFlags.Instance | BindingFlags.NonPublic);
if (acceptedCommandsField is null)
{
throw new MissingFieldException(nameof(ServiceBase), acceptedCommandsFieldName);
@ -501,8 +501,8 @@ namespace WinSW
private void SignalStopped()
{
using ServiceManager scm = ServiceManager.Open();
using Service sc = scm.OpenService(this.ServiceName, ServiceApis.ServiceAccess.QueryStatus);
using var scm = ServiceManager.Open();
using var sc = scm.OpenService(this.ServiceName, ServiceApis.ServiceAccess.QueryStatus);
sc.SetStatus(this.ServiceHandle, ServiceControllerStatus.Stopped);
}
@ -549,16 +549,16 @@ namespace WinSW
RedirectStandardError = logHandler?.ErrFileDisabled == false,
};
Dictionary<string, string> environment = this.config.EnvironmentVariables;
var environment = this.config.EnvironmentVariables;
if (environment.Count > 0)
{
var newEnvironment =
#if NETCOREAPP
#if NET
startInfo.Environment;
#else
startInfo.EnvironmentVariables;
#endif
foreach (KeyValuePair<string, string> pair in environment)
foreach (var pair in environment)
{
newEnvironment[pair.Key] = pair.Value;
}
@ -607,7 +607,7 @@ namespace WinSW
{
process.Exited += (sender, _) =>
{
Process process = (Process)sender!;
var process = (Process)sender!;
if (!process.EnableRaisingEvents)
{