mirror of https://github.com/winsw/winsw
Ensure basic console logging
parent
12525cc8fc
commit
2ab79083d4
|
@ -102,7 +102,7 @@ namespace WinSW
|
||||||
|
|
||||||
private static int SingleIntElement(XmlNode parent, string tagName, int defaultValue)
|
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);
|
return e is null ? defaultValue : int.Parse(e.InnerText, NumberFormatInfo.InvariantInfo);
|
||||||
}
|
}
|
||||||
|
@ -128,13 +128,13 @@ namespace WinSW
|
||||||
|
|
||||||
private string? SingleElementOrNull(string tagName)
|
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);
|
return n is null ? null : Environment.ExpandEnvironmentVariables(n.InnerText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SingleBoolElementOrDefault(string tagName, bool defaultValue)
|
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);
|
return e is null ? defaultValue : bool.Parse(e.InnerText);
|
||||||
}
|
}
|
||||||
|
@ -208,14 +208,14 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? argumentNode = this.ExtensionsConfiguration;
|
var argumentNode = this.ExtensionsConfiguration;
|
||||||
XmlNodeList? extensions = argumentNode?.SelectNodes("extension");
|
var extensions = argumentNode?.SelectNodes("extension");
|
||||||
if (extensions is null)
|
if (extensions is null)
|
||||||
{
|
{
|
||||||
return new List<string>(0);
|
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++)
|
for (int i = 0; i < extensions.Count; i++)
|
||||||
{
|
{
|
||||||
result.Add(XmlHelper.SingleAttribute<string>((XmlElement)extensions[i]!, "id"));
|
result.Add(XmlHelper.SingleAttribute<string>((XmlElement)extensions[i]!, "id"));
|
||||||
|
@ -239,7 +239,7 @@ namespace WinSW
|
||||||
string? mode = null;
|
string? mode = null;
|
||||||
|
|
||||||
// first, backward compatibility with older configuration
|
// first, backward compatibility with older configuration
|
||||||
XmlElement? e = (XmlElement?)this.root.SelectSingleNode("logmode");
|
var e = (XmlElement?)this.root.SelectSingleNode("logmode");
|
||||||
if (e != null)
|
if (e != null)
|
||||||
{
|
{
|
||||||
mode = e.InnerText;
|
mode = e.InnerText;
|
||||||
|
@ -272,7 +272,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
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
|
// this is more modern way, to support nested elements as configuration
|
||||||
e ??= (XmlElement?)this.root.SelectSingleNode("log")!; // WARNING: NRE
|
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);
|
return new RollingLogAppender(this.LogDirectory, this.LogName, this.OutFileDisabled, this.ErrFileDisabled, this.OutFilePattern, this.ErrFilePattern);
|
||||||
|
|
||||||
case "roll-by-time":
|
case "roll-by-time":
|
||||||
XmlNode? patternNode = e.SelectSingleNode("pattern");
|
var patternNode = e.SelectSingleNode("pattern");
|
||||||
if (patternNode is null)
|
if (patternNode is null)
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("Time Based rolling policy is specified but no pattern can be found in configuration XML.");
|
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);
|
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);
|
||||||
|
|
||||||
|
@ -313,18 +313,18 @@ namespace WinSW
|
||||||
|
|
||||||
case "roll-by-size-time":
|
case "roll-by-size-time":
|
||||||
sizeThreshold = SingleIntElement(e, "sizeThreshold", 10 * 1024) * RollingSizeTimeLogAppender.BytesPerKB;
|
sizeThreshold = SingleIntElement(e, "sizeThreshold", 10 * 1024) * RollingSizeTimeLogAppender.BytesPerKB;
|
||||||
XmlNode? filePatternNode = e.SelectSingleNode("pattern");
|
var filePatternNode = e.SelectSingleNode("pattern");
|
||||||
if (filePatternNode is null)
|
if (filePatternNode is null)
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but no pattern can be found in configuration XML.");
|
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;
|
TimeSpan? autoRollAtTime = null;
|
||||||
if (autoRollAtTimeNode != null)
|
if (autoRollAtTimeNode != null)
|
||||||
{
|
{
|
||||||
// validate it
|
// 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.");
|
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;
|
autoRollAtTime = autoRollAtTimeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlNode? zipolderthannumdaysNode = e.SelectSingleNode("zipOlderThanNumDays");
|
var zipolderthannumdaysNode = e.SelectSingleNode("zipOlderThanNumDays");
|
||||||
int? zipolderthannumdays = null;
|
int? zipolderthannumdays = null;
|
||||||
if (zipolderthannumdaysNode != null)
|
if (zipolderthannumdaysNode != null)
|
||||||
{
|
{
|
||||||
|
@ -345,7 +345,7 @@ namespace WinSW
|
||||||
zipolderthannumdays = zipolderthannumdaysValue;
|
zipolderthannumdays = zipolderthannumdaysValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlNode? zipdateformatNode = e.SelectSingleNode("zipDateFormat");
|
var zipdateformatNode = e.SelectSingleNode("zipDateFormat");
|
||||||
string zipdateformat = zipdateformatNode is null ? "yyyyMM" : zipdateformatNode.InnerText;
|
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);
|
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
|
get
|
||||||
{
|
{
|
||||||
XmlNodeList? nodeList = this.root.SelectNodes("depend");
|
var nodeList = this.root.SelectNodes("depend");
|
||||||
if (nodeList is null)
|
if (nodeList is null)
|
||||||
{
|
{
|
||||||
return base.ServiceDependencies;
|
return base.ServiceDependencies;
|
||||||
|
@ -404,7 +404,7 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
catch (ArgumentException e)
|
catch (ArgumentException e)
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
builder.AppendLine("Start mode in XML must be one of the following:");
|
builder.AppendLine("Start mode in XML must be one of the following:");
|
||||||
foreach (string sm in Enum.GetNames(typeof(ServiceStartMode)))
|
foreach (string sm in Enum.GetNames(typeof(ServiceStartMode)))
|
||||||
{
|
{
|
||||||
|
@ -457,13 +457,13 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNodeList? nodeList = this.root.SelectNodes("download");
|
var nodeList = this.root.SelectNodes("download");
|
||||||
if (nodeList is null)
|
if (nodeList is null)
|
||||||
{
|
{
|
||||||
return base.Downloads;
|
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++)
|
for (int i = 0; i < nodeList.Count; i++)
|
||||||
{
|
{
|
||||||
if (nodeList[i] is XmlElement element)
|
if (nodeList[i] is XmlElement element)
|
||||||
|
@ -480,25 +480,25 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNodeList? childNodes = this.root.SelectNodes("onfailure");
|
var childNodes = this.root.SelectNodes("onfailure");
|
||||||
if (childNodes is null)
|
if (childNodes is null)
|
||||||
{
|
{
|
||||||
return Array.Empty<SC_ACTION>();
|
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++)
|
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");
|
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,
|
"restart" => SC_ACTION_TYPE.SC_ACTION_RESTART,
|
||||||
"none" => SC_ACTION_TYPE.SC_ACTION_NONE,
|
"none" => SC_ACTION_TYPE.SC_ACTION_NONE,
|
||||||
"reboot" => SC_ACTION_TYPE.SC_ACTION_REBOOT,
|
"reboot" => SC_ACTION_TYPE.SC_ACTION_REBOOT,
|
||||||
_ => throw new Exception("Invalid failure action: " + action)
|
_ => 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);
|
result[i] = new SC_ACTION(type, delay != null ? ParseTimeSpan(delay.Value) : TimeSpan.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,11 +510,11 @@ namespace WinSW
|
||||||
|
|
||||||
protected string? GetServiceAccountPart(string subNodeName)
|
protected string? GetServiceAccountPart(string subNodeName)
|
||||||
{
|
{
|
||||||
XmlNode? node = this.root.SelectSingleNode("serviceaccount");
|
var node = this.root.SelectSingleNode("serviceaccount");
|
||||||
|
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
XmlNode? subNode = node.SelectSingleNode(subNodeName);
|
var subNode = node.SelectSingleNode(subNodeName);
|
||||||
if (subNode != null)
|
if (subNode != null)
|
||||||
{
|
{
|
||||||
return subNode.InnerText;
|
return subNode.InnerText;
|
||||||
|
@ -583,11 +583,11 @@ namespace WinSW
|
||||||
|
|
||||||
private Dictionary<string, string> LoadEnvironmentVariables()
|
private Dictionary<string, string> LoadEnvironmentVariables()
|
||||||
{
|
{
|
||||||
XmlNodeList nodeList = this.root.SelectNodes("env")!;
|
var nodeList = this.root.SelectNodes("env")!;
|
||||||
Dictionary<string, string> environment = new Dictionary<string, string>(nodeList.Count);
|
var environment = new Dictionary<string, string>(nodeList.Count);
|
||||||
for (int i = 0; i < nodeList.Count; i++)
|
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 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"));
|
string value = Environment.ExpandEnvironmentVariables(node.Attributes["value"]?.Value ?? throw new InvalidDataException("'value' is missing"));
|
||||||
environment[key] = value;
|
environment[key] = value;
|
||||||
|
@ -600,7 +600,7 @@ namespace WinSW
|
||||||
|
|
||||||
private ProcessCommand GetProcessCommand(string name)
|
private ProcessCommand GetProcessCommand(string name)
|
||||||
{
|
{
|
||||||
XmlNode? node = this.root.SelectSingleNode(name);
|
var node = this.root.SelectSingleNode(name);
|
||||||
return node is null ? default : new ProcessCommand
|
return node is null ? default : new ProcessCommand
|
||||||
{
|
{
|
||||||
Executable = GetInnerText(Names.Executable),
|
Executable = GetInnerText(Names.Executable),
|
||||||
|
|
|
@ -121,10 +121,10 @@ namespace WinSW
|
||||||
/// </exception>
|
/// </exception>
|
||||||
public async Task PerformAsync()
|
public async Task PerformAsync()
|
||||||
{
|
{
|
||||||
WebRequest request = WebRequest.Create(this.From);
|
var request = WebRequest.Create(this.From);
|
||||||
if (!string.IsNullOrEmpty(this.Proxy))
|
if (!string.IsNullOrEmpty(this.Proxy))
|
||||||
{
|
{
|
||||||
CustomProxyInformation proxyInformation = new CustomProxyInformation(this.Proxy!);
|
var proxyInformation = new CustomProxyInformation(this.Proxy!);
|
||||||
if (proxyInformation.Credentials != null)
|
if (proxyInformation.Credentials != null)
|
||||||
{
|
{
|
||||||
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
|
request.Proxy = new WebProxy(proxyInformation.ServerAddress, false, null, proxyInformation.Credentials);
|
||||||
|
@ -166,9 +166,9 @@ namespace WinSW
|
||||||
string tmpFilePath = this.To + ".tmp";
|
string tmpFilePath = this.To + ".tmp";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (WebResponse response = await request.GetResponseAsync().ConfigureAwait(false))
|
using (var response = await request.GetResponseAsync().ConfigureAwait(false))
|
||||||
using (Stream responseStream = response.GetResponseStream())
|
using (var responseStream = response.GetResponseStream())
|
||||||
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
|
using (var tmpStream = new FileStream(tmpFilePath, FileMode.Create))
|
||||||
{
|
{
|
||||||
if (supportsIfModifiedSince)
|
if (supportsIfModifiedSince)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace WinSW.Extensions
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Type? t = Type.GetType(className);
|
var t = Type.GetType(className);
|
||||||
if (t is null)
|
if (t is null)
|
||||||
{
|
{
|
||||||
throw new ExtensionException(id, "Class " + className + " does not exist");
|
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");
|
throw new ExtensionException(id, "Extension has been already loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlNode? extensionsConfig = this.ServiceConfig.ExtensionsConfiguration;
|
var extensionsConfig = this.ServiceConfig.ExtensionsConfiguration;
|
||||||
XmlElement? configNode = extensionsConfig is null ? null : extensionsConfig.SelectSingleNode("extension[@id='" + id + "'][1]") as XmlElement;
|
var configNode = extensionsConfig is null ? null : extensionsConfig.SelectSingleNode("extension[@id='" + id + "'][1]") as XmlElement;
|
||||||
if (configNode is null)
|
if (configNode is null)
|
||||||
{
|
{
|
||||||
throw new ExtensionException(id, "Cannot get the configuration entry");
|
throw new ExtensionException(id, "Cannot get the configuration entry");
|
||||||
|
@ -164,7 +164,7 @@ namespace WinSW.Extensions
|
||||||
var descriptor = WinSWExtensionDescriptor.FromXml(configNode);
|
var descriptor = WinSWExtensionDescriptor.FromXml(configNode);
|
||||||
if (descriptor.Enabled)
|
if (descriptor.Enabled)
|
||||||
{
|
{
|
||||||
IWinSWExtension extension = CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
|
var extension = CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
|
||||||
extension.Descriptor = descriptor;
|
extension.Descriptor = descriptor;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -243,10 +243,10 @@ namespace WinSW
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task CopyStreamWithDateRotationAsync(StreamReader reader, string ext)
|
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();
|
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;
|
string? line;
|
||||||
while ((line = await reader.ReadLineAsync()) != null)
|
while ((line = await reader.ReadLineAsync()) != null)
|
||||||
{
|
{
|
||||||
|
@ -302,7 +302,7 @@ namespace WinSW
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task CopyStreamWithRotationAsync(StreamReader reader, string ext)
|
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;
|
long fileLength = new FileInfo(this.BaseLogFileName + ext).Length;
|
||||||
|
|
||||||
string? line;
|
string? line;
|
||||||
|
@ -426,20 +426,20 @@ namespace WinSW
|
||||||
private async Task CopyStreamWithRotationAsync(StreamReader reader, string extension)
|
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
|
// 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)!;
|
string? baseDirectory = Path.GetDirectoryName(this.BaseLogFileName)!;
|
||||||
var baseFileName = Path.GetFileName(this.BaseLogFileName);
|
string? baseFileName = Path.GetFileName(this.BaseLogFileName);
|
||||||
var logFile = this.BaseLogFileName + extension;
|
string? logFile = this.BaseLogFileName + extension;
|
||||||
|
|
||||||
var writer = this.CreateWriter(new FileStream(logFile, FileMode.Append));
|
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
|
// 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)
|
if (this.AutoRollAtTime is TimeSpan autoRollAtTime)
|
||||||
{
|
{
|
||||||
// Run at start
|
// Run at start
|
||||||
var tickTime = this.SetupRollTimer(autoRollAtTime);
|
double tickTime = this.SetupRollTimer(autoRollAtTime);
|
||||||
var timer = new System.Timers.Timer(tickTime);
|
var timer = new System.Timers.Timer(tickTime);
|
||||||
timer.Elapsed += (_, _) =>
|
timer.Elapsed += (_, _) =>
|
||||||
{
|
{
|
||||||
|
@ -451,8 +451,8 @@ namespace WinSW
|
||||||
writer.Dispose();
|
writer.Dispose();
|
||||||
|
|
||||||
var now = DateTime.Now.AddDays(-1);
|
var now = DateTime.Now.AddDays(-1);
|
||||||
var nextFileNumber = this.GetNextFileNumber(extension, baseDirectory, baseFileName, now);
|
int 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));
|
string? nextFileName = Path.Combine(baseDirectory, string.Format("{0}.{1}.#{2:D4}{3}", baseFileName, now.ToString(this.FilePattern), nextFileNumber, extension));
|
||||||
File.Move(logFile, nextFileName);
|
File.Move(logFile, nextFileName);
|
||||||
|
|
||||||
writer = this.CreateWriter(new FileStream(logFile, FileMode.Create));
|
writer = this.CreateWriter(new FileStream(logFile, FileMode.Create));
|
||||||
|
@ -488,8 +488,8 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
// roll file
|
// roll file
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
var nextFileNumber = this.GetNextFileNumber(extension, baseDirectory, baseFileName, now);
|
int nextFileNumber = this.GetNextFileNumber(extension, baseDirectory, baseFileName, now);
|
||||||
var nextFileName = Path.Combine(
|
string? nextFileName = Path.Combine(
|
||||||
baseDirectory,
|
baseDirectory,
|
||||||
string.Format("{0}.{1}.#{2:D4}{3}", baseFileName, now.ToString(this.FilePattern), nextFileNumber, extension));
|
string.Format("{0}.{1}.#{2:D4}{3}", baseFileName, now.ToString(this.FilePattern), nextFileNumber, extension));
|
||||||
File.Move(logFile, nextFileName);
|
File.Move(logFile, nextFileName);
|
||||||
|
@ -589,21 +589,21 @@ namespace WinSW
|
||||||
|
|
||||||
private int GetNextFileNumber(string ext, string baseDirectory, string baseFileName, DateTime now)
|
private int GetNextFileNumber(string ext, string baseDirectory, string baseFileName, DateTime now)
|
||||||
{
|
{
|
||||||
var nextFileNumber = 0;
|
int nextFileNumber = 0;
|
||||||
var files = Directory.GetFiles(baseDirectory, string.Format("{0}.{1}.#*{2}", baseFileName, now.ToString(this.FilePattern), ext));
|
string[]? files = Directory.GetFiles(baseDirectory, string.Format("{0}.{1}.#*{2}", baseFileName, now.ToString(this.FilePattern), ext));
|
||||||
if (files.Length == 0)
|
if (files.Length == 0)
|
||||||
{
|
{
|
||||||
nextFileNumber = 1;
|
nextFileNumber = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var f in files)
|
foreach (string? f in files)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var filenameOnly = Path.GetFileNameWithoutExtension(f);
|
string? filenameOnly = Path.GetFileNameWithoutExtension(f);
|
||||||
var hashIndex = filenameOnly.IndexOf('#');
|
int hashIndex = filenameOnly.IndexOf('#');
|
||||||
var lastNumberAsString = filenameOnly.Substring(hashIndex + 1, 4);
|
string? lastNumberAsString = filenameOnly.Substring(hashIndex + 1, 4);
|
||||||
if (int.TryParse(lastNumberAsString, out int lastNumber))
|
if (int.TryParse(lastNumberAsString, out int lastNumber))
|
||||||
{
|
{
|
||||||
if (lastNumber > nextFileNumber)
|
if (lastNumber > nextFileNumber)
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace WinSW.Native
|
||||||
IntPtr.Zero,
|
IntPtr.Zero,
|
||||||
ref inBufferSize);
|
ref inBufferSize);
|
||||||
|
|
||||||
IntPtr inBuffer = Marshal.AllocCoTaskMem(inBufferSize);
|
var inBuffer = Marshal.AllocCoTaskMem(inBufferSize);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!CredPackAuthenticationBuffer(
|
if (!CredPackAuthenticationBuffer(
|
||||||
|
@ -33,7 +33,7 @@ namespace WinSW.Native
|
||||||
Throw.Command.Win32Exception("Failed to pack auth buffer.");
|
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)),
|
Size = Marshal.SizeOf(typeof(CREDUI_INFO)),
|
||||||
CaptionText = caption,
|
CaptionText = caption,
|
||||||
|
@ -47,7 +47,7 @@ namespace WinSW.Native
|
||||||
ref authPackage,
|
ref authPackage,
|
||||||
inBuffer,
|
inBuffer,
|
||||||
inBufferSize,
|
inBufferSize,
|
||||||
out IntPtr outBuffer,
|
out var outBuffer,
|
||||||
out uint outBufferSize,
|
out uint outBufferSize,
|
||||||
ref save,
|
ref save,
|
||||||
CREDUIWIN_GENERIC);
|
CREDUIWIN_GENERIC);
|
||||||
|
|
|
@ -11,24 +11,24 @@ namespace WinSW.Native
|
||||||
/// <exception cref="CommandException" />
|
/// <exception cref="CommandException" />
|
||||||
internal static unsafe bool UpdateCompanyName(string path, string outputPath, string companyName)
|
internal static unsafe bool UpdateCompanyName(string path, string outputPath, string companyName)
|
||||||
{
|
{
|
||||||
IntPtr module = LoadLibraryW(path);
|
var module = LoadLibraryW(path);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IntPtr verInfo = FindResourceW(module, VS_VERSION_INFO, RT_VERSION);
|
var verInfo = FindResourceW(module, VS_VERSION_INFO, RT_VERSION);
|
||||||
if (verInfo == IntPtr.Zero)
|
if (verInfo == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Exit();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr resData = LoadResource(module, verInfo);
|
var resData = LoadResource(module, verInfo);
|
||||||
if (resData == IntPtr.Zero)
|
if (resData == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Exit();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr resAddr = LockResource(resData);
|
var resAddr = LockResource(resData);
|
||||||
|
|
||||||
IntPtr address = resAddr;
|
var address = resAddr;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
short length = ((short*)address)[0];
|
short length = ((short*)address)[0];
|
||||||
|
@ -81,7 +81,7 @@ namespace WinSW.Native
|
||||||
int newLength = companyName.Length + 1;
|
int newLength = companyName.Length + 1;
|
||||||
Debug.Assert(newLength > 12 && newLength <= 16);
|
Debug.Assert(newLength > 12 && newLength <= 16);
|
||||||
|
|
||||||
IntPtr newAddress = Marshal.AllocHGlobal(length);
|
var newAddress = Marshal.AllocHGlobal(length);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Buffer.MemoryCopy((void*)resAddr, (void*)newAddress, length, length);
|
Buffer.MemoryCopy((void*)resAddr, (void*)newAddress, length, length);
|
||||||
|
@ -94,7 +94,7 @@ namespace WinSW.Native
|
||||||
|
|
||||||
File.Copy(path, outputPath, true);
|
File.Copy(path, outputPath, true);
|
||||||
|
|
||||||
IntPtr update = BeginUpdateResourceW(outputPath, false);
|
var update = BeginUpdateResourceW(outputPath, false);
|
||||||
if (update == IntPtr.Zero)
|
if (update == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Exit();
|
Exit();
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace WinSW.Native
|
||||||
/// <exception cref="Win32Exception" />
|
/// <exception cref="Win32Exception" />
|
||||||
internal static void AddServiceLogonRight(ref string userName)
|
internal static void AddServiceLogonRight(ref string userName)
|
||||||
{
|
{
|
||||||
IntPtr sid = GetAccountSid(ref userName);
|
var sid = GetAccountSid(ref userName);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ namespace WinSW.Native
|
||||||
|
|
||||||
_ = LookupAccountName(null, accountName, IntPtr.Zero, ref sidSize, null, ref domainNameLength, out _);
|
_ = LookupAccountName(null, accountName, IntPtr.Zero, ref sidSize, null, ref domainNameLength, out _);
|
||||||
|
|
||||||
IntPtr sid = Marshal.AllocHGlobal(sidSize);
|
var sid = Marshal.AllocHGlobal(sidSize);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string? domainName = domainNameLength == 0 ? null : new string('\0', domainNameLength - 1);
|
string? domainName = domainNameLength == 0 ? null : new string('\0', domainNameLength - 1);
|
||||||
|
@ -64,7 +64,7 @@ namespace WinSW.Native
|
||||||
/// <exception cref="Win32Exception" />
|
/// <exception cref="Win32Exception" />
|
||||||
private static void AddAccountRight(IntPtr sid, string rightName)
|
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)
|
if (status != 0)
|
||||||
{
|
{
|
||||||
throw new Win32Exception(LsaNtStatusToWinError(status));
|
throw new Win32Exception(LsaNtStatusToWinError(status));
|
||||||
|
@ -72,7 +72,7 @@ namespace WinSW.Native
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LSA_UNICODE_STRING userRight = new LSA_UNICODE_STRING
|
var userRight = new LSA_UNICODE_STRING
|
||||||
{
|
{
|
||||||
Buffer = rightName,
|
Buffer = rightName,
|
||||||
Length = (ushort)(rightName.Length * sizeof(char)),
|
Length = (ushort)(rightName.Length * sizeof(char)),
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace WinSW.Native
|
||||||
/// <exception cref="CommandException" />
|
/// <exception cref="CommandException" />
|
||||||
internal static ServiceManager Open(ServiceManagerAccess access = ServiceManagerAccess.All)
|
internal static ServiceManager Open(ServiceManagerAccess access = ServiceManagerAccess.All)
|
||||||
{
|
{
|
||||||
IntPtr handle = OpenSCManager(null, null, access);
|
var handle = OpenSCManager(null, null, access);
|
||||||
if (handle == IntPtr.Zero)
|
if (handle == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Throw.Command.Win32Exception("Failed to open the service control manager database.");
|
Throw.Command.Win32Exception("Failed to open the service control manager database.");
|
||||||
|
@ -77,7 +77,7 @@ namespace WinSW.Native
|
||||||
string? username,
|
string? username,
|
||||||
string? password)
|
string? password)
|
||||||
{
|
{
|
||||||
IntPtr handle = ServiceApis.CreateService(
|
var handle = ServiceApis.CreateService(
|
||||||
this.handle,
|
this.handle,
|
||||||
serviceName,
|
serviceName,
|
||||||
displayName,
|
displayName,
|
||||||
|
@ -113,7 +113,7 @@ namespace WinSW.Native
|
||||||
out _,
|
out _,
|
||||||
ref resume);
|
ref resume);
|
||||||
|
|
||||||
IntPtr services = Marshal.AllocHGlobal(bytesNeeded);
|
var services = Marshal.AllocHGlobal(bytesNeeded);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!EnumServicesStatus(
|
if (!EnumServicesStatus(
|
||||||
|
@ -141,7 +141,7 @@ namespace WinSW.Native
|
||||||
/// <exception cref="CommandException" />
|
/// <exception cref="CommandException" />
|
||||||
internal unsafe Service OpenService(char* serviceName, ServiceAccess access = ServiceAccess.All)
|
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)
|
if (serviceHandle == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Throw.Command.Win32Exception("Failed to open the service.");
|
Throw.Command.Win32Exception("Failed to open the service.");
|
||||||
|
@ -153,7 +153,7 @@ namespace WinSW.Native
|
||||||
/// <exception cref="CommandException" />
|
/// <exception cref="CommandException" />
|
||||||
internal Service OpenService(string serviceName, ServiceAccess access = ServiceAccess.All)
|
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)
|
if (serviceHandle == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Throw.Command.Win32Exception("Failed to open the service.");
|
Throw.Command.Win32Exception("Failed to open the service.");
|
||||||
|
@ -164,7 +164,7 @@ namespace WinSW.Native
|
||||||
|
|
||||||
internal bool ServiceExists(string serviceName)
|
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)
|
if (serviceHandle == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -202,7 +202,7 @@ namespace WinSW.Native
|
||||||
0,
|
0,
|
||||||
out int bytesNeeded);
|
out int bytesNeeded);
|
||||||
|
|
||||||
IntPtr config = Marshal.AllocHGlobal(bytesNeeded);
|
var config = Marshal.AllocHGlobal(bytesNeeded);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!QueryServiceConfig(
|
if (!QueryServiceConfig(
|
||||||
|
@ -231,7 +231,7 @@ namespace WinSW.Native
|
||||||
if (!QueryServiceStatusEx(
|
if (!QueryServiceStatusEx(
|
||||||
this.handle,
|
this.handle,
|
||||||
ServiceStatusType.ProcessInfo,
|
ServiceStatusType.ProcessInfo,
|
||||||
out SERVICE_STATUS_PROCESS status,
|
out var status,
|
||||||
sizeof(SERVICE_STATUS_PROCESS),
|
sizeof(SERVICE_STATUS_PROCESS),
|
||||||
out _))
|
out _))
|
||||||
{
|
{
|
||||||
|
@ -247,7 +247,7 @@ namespace WinSW.Native
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!QueryServiceStatus(this.handle, out SERVICE_STATUS status))
|
if (!QueryServiceStatus(this.handle, out var status))
|
||||||
{
|
{
|
||||||
Throw.Command.Win32Exception("Failed to query service status.");
|
Throw.Command.Win32Exception("Failed to query service status.");
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ namespace WinSW.Native
|
||||||
/// <exception cref="CommandException" />
|
/// <exception cref="CommandException" />
|
||||||
internal void SetStatus(IntPtr statusHandle, ServiceControllerStatus state)
|
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.");
|
Throw.Command.Win32Exception("Failed to query service status.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ namespace WinSW.Native
|
||||||
var serviceName = new ReadOnlySpan<char>(this.ServiceName, new ReadOnlySpan<char>(this.ServiceName, 256).IndexOf('\0'));
|
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'));
|
var displayName = new ReadOnlySpan<char>(this.DisplayName, new ReadOnlySpan<char>(this.DisplayName, 256).IndexOf('\0'));
|
||||||
|
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
return string.Concat(displayName, " (", serviceName, ")");
|
return string.Concat(displayName, " (", serviceName, ")");
|
||||||
#else
|
#else
|
||||||
return string.Concat(displayName.ToString(), " (", serviceName.ToString(), ")");
|
return string.Concat(displayName.ToString(), " (", serviceName.ToString(), ")");
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace WinSW.Native
|
||||||
internal static void Win32Exception(int error, string message)
|
internal static void Win32Exception(int error, string message)
|
||||||
{
|
{
|
||||||
Debug.Assert(error != 0);
|
Debug.Assert(error != 0);
|
||||||
Win32Exception inner = new Win32Exception(error);
|
var inner = new Win32Exception(error);
|
||||||
Debug.Assert(message.EndsWith("."));
|
Debug.Assert(message.EndsWith("."));
|
||||||
throw new CommandException(message + ' ' + inner.Message, inner);
|
throw new CommandException(message + ' ' + inner.Message, inner);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ namespace WinSW.Native
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static void Win32Exception()
|
internal static void Win32Exception()
|
||||||
{
|
{
|
||||||
Win32Exception inner = new Win32Exception();
|
var inner = new Win32Exception();
|
||||||
Debug.Assert(inner.NativeErrorCode != 0);
|
Debug.Assert(inner.NativeErrorCode != 0);
|
||||||
throw new CommandException(inner);
|
throw new CommandException(inner);
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ namespace WinSW.Native
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static void Win32Exception(string message)
|
internal static void Win32Exception(string message)
|
||||||
{
|
{
|
||||||
Win32Exception inner = new Win32Exception();
|
var inner = new Win32Exception();
|
||||||
Debug.Assert(inner.NativeErrorCode != 0);
|
Debug.Assert(inner.NativeErrorCode != 0);
|
||||||
Debug.Assert(message.EndsWith("."));
|
Debug.Assert(message.EndsWith("."));
|
||||||
throw new CommandException(message + ' ' + inner.Message, inner);
|
throw new CommandException(message + ' ' + inner.Message, inner);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Licensed to the .NET Foundation under one or more agreements.
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
#if !NETCOREAPP
|
#if !NET
|
||||||
namespace System.Diagnostics.CodeAnalysis
|
namespace System.Diagnostics.CodeAnalysis
|
||||||
{
|
{
|
||||||
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
|
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
|
||||||
|
|
|
@ -40,15 +40,15 @@ namespace WinSW
|
||||||
|
|
||||||
private PeriodicityType DeterminePeriodicityType()
|
private PeriodicityType DeterminePeriodicityType()
|
||||||
{
|
{
|
||||||
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
|
var periodicRollingCalendar = new PeriodicRollingCalendar(this.format, this.period);
|
||||||
DateTime epoch = new DateTime(1970, 1, 1);
|
var epoch = new DateTime(1970, 1, 1);
|
||||||
|
|
||||||
foreach (PeriodicityType i in ValidOrderedList)
|
foreach (var i in ValidOrderedList)
|
||||||
{
|
{
|
||||||
string r0 = epoch.ToString(this.format);
|
string r0 = epoch.ToString(this.format);
|
||||||
periodicRollingCalendar.Periodicity = i;
|
periodicRollingCalendar.Periodicity = i;
|
||||||
|
|
||||||
DateTime next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
|
var next = periodicRollingCalendar.NextTriggeringTime(epoch, 1);
|
||||||
string r1 = next.ToString(this.format);
|
string r1 = next.ToString(this.format);
|
||||||
|
|
||||||
if (r0 != r1)
|
if (r0 != r1)
|
||||||
|
@ -91,7 +91,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
DateTime now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
if (now > this.nextRoll)
|
if (now > this.nextRoll)
|
||||||
{
|
{
|
||||||
this.currentRoll = now;
|
this.currentRoll = now;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#if !NETCOREAPP
|
#if !NET
|
||||||
using System;
|
using System;
|
||||||
#endif
|
#endif
|
||||||
using System.IO;
|
using System.IO;
|
||||||
#if !NETCOREAPP
|
#if !NET
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ namespace WinSW.Util
|
||||||
{
|
{
|
||||||
public static void MoveOrReplaceFile(string sourceFileName, string destFileName)
|
public static void MoveOrReplaceFile(string sourceFileName, string destFileName)
|
||||||
{
|
{
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
File.Move(sourceFileName, destFileName, true);
|
File.Move(sourceFileName, destFileName, true);
|
||||||
#else
|
#else
|
||||||
string sourceFilePath = Path.GetFullPath(sourceFileName);
|
string sourceFilePath = Path.GetFullPath(sourceFileName);
|
||||||
|
@ -24,7 +24,7 @@ namespace WinSW.Util
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if !NETCOREAPP
|
#if !NET
|
||||||
|
|
||||||
private static Exception GetExceptionForLastWin32Error(string path) => Marshal.GetLastWin32Error() switch
|
private static Exception GetExceptionForLastWin32Error(string path) => Marshal.GetLastWin32Error() switch
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace WinSW.Util
|
||||||
{
|
{
|
||||||
StopPrivate(process, millisecondsTimeout);
|
StopPrivate(process, millisecondsTimeout);
|
||||||
|
|
||||||
foreach (Process child in GetChildren(process))
|
foreach (var child in GetChildren(process))
|
||||||
{
|
{
|
||||||
using (child)
|
using (child)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ namespace WinSW.Util
|
||||||
|
|
||||||
internal static void StopDescendants(this Process process, int millisecondsTimeout)
|
internal static void StopDescendants(this Process process, int millisecondsTimeout)
|
||||||
{
|
{
|
||||||
foreach (Process child in GetChildren(process))
|
foreach (var child in GetChildren(process))
|
||||||
{
|
{
|
||||||
using (child)
|
using (child)
|
||||||
{
|
{
|
||||||
|
@ -40,12 +40,12 @@ namespace WinSW.Util
|
||||||
|
|
||||||
internal static unsafe List<Process> GetChildren(this Process process)
|
internal static unsafe List<Process> GetChildren(this Process process)
|
||||||
{
|
{
|
||||||
DateTime startTime = process.StartTime;
|
var startTime = process.StartTime;
|
||||||
int processId = process.Id;
|
int processId = process.Id;
|
||||||
|
|
||||||
var children = new List<Process>();
|
var children = new List<Process>();
|
||||||
|
|
||||||
foreach (Process other in Process.GetProcesses())
|
foreach (var other in Process.GetProcesses())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -54,12 +54,12 @@ namespace WinSW.Util
|
||||||
goto Next;
|
goto Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr handle = other.Handle;
|
var handle = other.Handle;
|
||||||
|
|
||||||
if (NtQueryInformationProcess(
|
if (NtQueryInformationProcess(
|
||||||
handle,
|
handle,
|
||||||
PROCESSINFOCLASS.ProcessBasicInformation,
|
PROCESSINFOCLASS.ProcessBasicInformation,
|
||||||
out PROCESS_BASIC_INFORMATION information,
|
out var information,
|
||||||
sizeof(PROCESS_BASIC_INFORMATION)) != 0)
|
sizeof(PROCESS_BASIC_INFORMATION)) != 0)
|
||||||
{
|
{
|
||||||
goto Next;
|
goto Next;
|
||||||
|
@ -119,7 +119,7 @@ namespace WinSW.Util
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
process.Kill();
|
process.Kill();
|
||||||
#else
|
#else
|
||||||
try
|
try
|
||||||
|
@ -169,7 +169,7 @@ namespace WinSW.Util
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
process.Kill();
|
process.Kill();
|
||||||
#else
|
#else
|
||||||
try
|
try
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace WinSW.Util
|
||||||
/// <exception cref="CommandException" />
|
/// <exception cref="CommandException" />
|
||||||
internal static unsafe DateTime GetLastWriteTime(this RegistryKey registryKey)
|
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)
|
if (error != Errors.ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
Throw.Command.Win32Exception(error, "Failed to query registry key.");
|
Throw.Command.Win32Exception(error, "Failed to query registry key.");
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace WinSW.Util
|
||||||
/// <exception cref="InvalidDataException">The required element is missing</exception>
|
/// <exception cref="InvalidDataException">The required element is missing</exception>
|
||||||
public static string? SingleElement(XmlNode node, string tagName, bool optional)
|
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)
|
if (n is null && !optional)
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
|
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>
|
/// <exception cref="InvalidDataException">The required element is missing</exception>
|
||||||
public static XmlNode? SingleNode(XmlNode node, string tagName, bool optional)
|
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)
|
if (n is null && !optional)
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
|
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
|
||||||
|
|
|
@ -23,13 +23,13 @@ namespace WinSW.Plugins.SharedDirectoryMapper
|
||||||
|
|
||||||
public SharedDirectoryMapper(bool enableMapping, string directoryUNC, string driveLabel)
|
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);
|
this.entries.Add(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Configure(XmlServiceConfig config, XmlNode node)
|
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)
|
if (mapNodes != null)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < mapNodes.Count; i++)
|
for (int i = 0; i < mapNodes.Count; i++)
|
||||||
|
@ -44,7 +44,7 @@ namespace WinSW.Plugins.SharedDirectoryMapper
|
||||||
|
|
||||||
public override void OnWrapperStarted()
|
public override void OnWrapperStarted()
|
||||||
{
|
{
|
||||||
foreach (SharedDirectoryMapperConfig config in this.entries)
|
foreach (var config in this.entries)
|
||||||
{
|
{
|
||||||
string label = config.Label;
|
string label = config.Label;
|
||||||
string uncPath = config.UNCPath;
|
string uncPath = config.UNCPath;
|
||||||
|
@ -72,7 +72,7 @@ namespace WinSW.Plugins.SharedDirectoryMapper
|
||||||
|
|
||||||
public override void BeforeWrapperStopped()
|
public override void BeforeWrapperStopped()
|
||||||
{
|
{
|
||||||
foreach (SharedDirectoryMapperConfig config in this.entries)
|
foreach (var config in this.entries)
|
||||||
{
|
{
|
||||||
string label = config.Label;
|
string label = config.Label;
|
||||||
if (config.EnableMapping)
|
if (config.EnableMapping)
|
||||||
|
@ -88,7 +88,7 @@ namespace WinSW.Plugins.SharedDirectoryMapper
|
||||||
|
|
||||||
private void ThrowExtensionException(int error, string message)
|
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);
|
throw new ExtensionException(this.Descriptor.Id, $"{this.DisplayName}: {message} {inner.Message}", inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace WinSW.Tests
|
||||||
{
|
{
|
||||||
const string commandName = "unknown";
|
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);
|
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);
|
Assert.Equal(OldCompanyName, FileVersionInfo.GetVersionInfo(inputPath).CompanyName);
|
||||||
|
|
||||||
// deny write access
|
// deny write access
|
||||||
using FileStream file = File.OpenRead(inputPath);
|
using var file = File.OpenRead(inputPath);
|
||||||
|
|
||||||
string outputPath = Path.GetTempFileName();
|
string outputPath = Path.GetTempFileName();
|
||||||
Program.TestExecutablePath = inputPath;
|
Program.TestExecutablePath = inputPath;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.IO;
|
||||||
using System.IO;
|
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using WinSW.Tests.Util;
|
using WinSW.Tests.Util;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
@ -15,7 +14,7 @@ namespace WinSW.Tests.Configuration
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AllOptionsConfigShouldDeclareDefaults()
|
public void AllOptionsConfigShouldDeclareDefaults()
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = Load("complete");
|
var config = Load("complete");
|
||||||
|
|
||||||
Assert.Equal("myapp", config.Name);
|
Assert.Equal("myapp", config.Name);
|
||||||
Assert.Equal("%BASE%\\myExecutable.exe", config.Executable);
|
Assert.Equal("%BASE%\\myExecutable.exe", config.Executable);
|
||||||
|
@ -26,7 +25,7 @@ namespace WinSW.Tests.Configuration
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MinimalConfigShouldDeclareDefaults()
|
public void MinimalConfigShouldDeclareDefaults()
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = Load("minimal");
|
var config = Load("minimal");
|
||||||
|
|
||||||
Assert.Equal("myapp", config.Name);
|
Assert.Equal("myapp", config.Name);
|
||||||
Assert.Equal("%BASE%\\myExecutable.exe", config.Executable);
|
Assert.Equal("%BASE%\\myExecutable.exe", config.Executable);
|
||||||
|
@ -41,7 +40,7 @@ namespace WinSW.Tests.Configuration
|
||||||
string path = Path.Combine(directory, $@"samples\sample-{exampleName}.xml");
|
string path = Path.Combine(directory, $@"samples\sample-{exampleName}.xml");
|
||||||
Assert.True(File.Exists(path));
|
Assert.True(File.Exists(path));
|
||||||
|
|
||||||
XmlDocument dom = new XmlDocument();
|
var dom = new XmlDocument();
|
||||||
dom.Load(path);
|
dom.Load(path);
|
||||||
return new XmlServiceConfig(dom);
|
return new XmlServiceConfig(dom);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace WinSW.Tests
|
||||||
public void Roundtrip_Defaults()
|
public void Roundtrip_Defaults()
|
||||||
{
|
{
|
||||||
// Roundtrip data
|
// Roundtrip data
|
||||||
Download d = new Download(From, To);
|
var d = new Download(From, To);
|
||||||
var config = ConfigXmlBuilder.Create(this.output)
|
var config = ConfigXmlBuilder.Create(this.output)
|
||||||
.WithDownload(d)
|
.WithDownload(d)
|
||||||
.ToServiceConfig(true);
|
.ToServiceConfig(true);
|
||||||
|
@ -39,7 +39,7 @@ namespace WinSW.Tests
|
||||||
public void Roundtrip_BasicAuth()
|
public void Roundtrip_BasicAuth()
|
||||||
{
|
{
|
||||||
// Roundtrip data
|
// 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)
|
var config = ConfigXmlBuilder.Create(this.output)
|
||||||
.WithDownload(d)
|
.WithDownload(d)
|
||||||
.ToServiceConfig(true);
|
.ToServiceConfig(true);
|
||||||
|
@ -57,7 +57,7 @@ namespace WinSW.Tests
|
||||||
public void Roundtrip_SSPI()
|
public void Roundtrip_SSPI()
|
||||||
{
|
{
|
||||||
// Roundtrip data
|
// 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)
|
var config = ConfigXmlBuilder.Create(this.output)
|
||||||
.WithDownload(d)
|
.WithDownload(d)
|
||||||
.ToServiceConfig(true);
|
.ToServiceConfig(true);
|
||||||
|
@ -105,7 +105,7 @@ namespace WinSW.Tests
|
||||||
[InlineData(false)]
|
[InlineData(false)]
|
||||||
public void Download_FailOnError(bool failOnError)
|
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)
|
var config = ConfigXmlBuilder.Create(this.output)
|
||||||
.WithDownload(d)
|
.WithDownload(d)
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace WinSW.Tests
|
||||||
|
|
||||||
public DownloadTests()
|
public DownloadTests()
|
||||||
{
|
{
|
||||||
TcpListener tcpListener = new TcpListener(IPAddress.Loopback, 0);
|
var tcpListener = new TcpListener(IPAddress.Loopback, 0);
|
||||||
tcpListener.Start();
|
tcpListener.Start();
|
||||||
int port = ((IPEndPoint)tcpListener.LocalEndpoint).Port;
|
int port = ((IPEndPoint)tcpListener.LocalEndpoint).Port;
|
||||||
string prefix = $"http://localhost:{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)
|
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}/";
|
string prefix = $"{this.globalPrefix}{path}/";
|
||||||
listener.Prefixes.Add(prefix);
|
listener.Prefixes.Add(prefix);
|
||||||
listener.AuthenticationSchemes = authenticationSchemes;
|
listener.AuthenticationSchemes = authenticationSchemes;
|
||||||
|
@ -72,7 +72,7 @@ namespace WinSW.Tests
|
||||||
|
|
||||||
async Task ListenAsync()
|
async Task ListenAsync()
|
||||||
{
|
{
|
||||||
HttpListenerContext context = await listener.GetContextAsync();
|
var context = await listener.GetContextAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
server(context);
|
server(context);
|
||||||
|
@ -136,7 +136,7 @@ namespace WinSW.Tests
|
||||||
},
|
},
|
||||||
context =>
|
context =>
|
||||||
{
|
{
|
||||||
HttpListenerBasicIdentity identity = (HttpListenerBasicIdentity)context.User.Identity;
|
var identity = (HttpListenerBasicIdentity)context.User.Identity;
|
||||||
if (identity.Name != username || identity.Password != password)
|
if (identity.Name != username || identity.Password != password)
|
||||||
{
|
{
|
||||||
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||||
|
@ -152,8 +152,8 @@ namespace WinSW.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task TestHttp_IfModifiedSince_ModifiedAsync()
|
public async Task TestHttp_IfModifiedSince_ModifiedAsync()
|
||||||
{
|
{
|
||||||
DateTime lastModified = DateTime.Now.TrimToSeconds();
|
var lastModified = DateTime.Now.TrimToSeconds();
|
||||||
DateTime prevModified = lastModified.AddDays(-1);
|
var prevModified = lastModified.AddDays(-1);
|
||||||
|
|
||||||
await this.TestClientServerAsync(
|
await this.TestClientServerAsync(
|
||||||
async (source, dest) =>
|
async (source, dest) =>
|
||||||
|
@ -180,7 +180,7 @@ namespace WinSW.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task TestHttp_IfModifiedSince_NotModifiedAsync()
|
public async Task TestHttp_IfModifiedSince_NotModifiedAsync()
|
||||||
{
|
{
|
||||||
DateTime lastModified = DateTime.Now.TrimToSeconds();
|
var lastModified = DateTime.Now.TrimToSeconds();
|
||||||
|
|
||||||
await this.TestClientServerAsync(
|
await this.TestClientServerAsync(
|
||||||
async (source, dest) =>
|
async (source, dest) =>
|
||||||
|
@ -210,7 +210,7 @@ namespace WinSW.Tests
|
||||||
await this.TestClientServerAsync(
|
await this.TestClientServerAsync(
|
||||||
async (source, dest) =>
|
async (source, dest) =>
|
||||||
{
|
{
|
||||||
WebException exception = await Assert.ThrowsAsync<WebException>(
|
var exception = await Assert.ThrowsAsync<WebException>(
|
||||||
async () => await new Download(source, dest).PerformAsync());
|
async () => await new Download(source, dest).PerformAsync());
|
||||||
|
|
||||||
Assert.Equal(WebExceptionStatus.ProtocolError, exception.Status);
|
Assert.Equal(WebExceptionStatus.ProtocolError, exception.Status);
|
||||||
|
|
|
@ -41,7 +41,7 @@ $@"<service>
|
||||||
[Fact]
|
[Fact]
|
||||||
public void LoadExtensions()
|
public void LoadExtensions()
|
||||||
{
|
{
|
||||||
WinSWExtensionManager manager = new WinSWExtensionManager(this.serviceConfig);
|
var manager = new WinSWExtensionManager(this.serviceConfig);
|
||||||
manager.LoadExtensions();
|
manager.LoadExtensions();
|
||||||
Assert.Equal(2, manager.Extensions.Count);
|
Assert.Equal(2, manager.Extensions.Count);
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ $@"<service>
|
||||||
[Fact]
|
[Fact]
|
||||||
public void StartStopExtension()
|
public void StartStopExtension()
|
||||||
{
|
{
|
||||||
WinSWExtensionManager manager = new WinSWExtensionManager(this.serviceConfig);
|
var manager = new WinSWExtensionManager(this.serviceConfig);
|
||||||
manager.LoadExtensions();
|
manager.LoadExtensions();
|
||||||
manager.FireOnWrapperStarted();
|
manager.FireOnWrapperStarted();
|
||||||
manager.FireBeforeWrapperStopped();
|
manager.FireBeforeWrapperStopped();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
@ -14,10 +14,10 @@ namespace WinSW.Tests.Extensions
|
||||||
[ElevatedFact]
|
[ElevatedFact]
|
||||||
public void TestMap()
|
public void TestMap()
|
||||||
{
|
{
|
||||||
using TestData data = TestData.Create();
|
using var data = TestData.Create();
|
||||||
|
|
||||||
const string label = "W:";
|
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();
|
mapper.OnWrapperStarted();
|
||||||
Assert.True(Directory.Exists($@"{label}\"));
|
Assert.True(Directory.Exists($@"{label}\"));
|
||||||
|
@ -28,10 +28,10 @@ namespace WinSW.Tests.Extensions
|
||||||
[ElevatedFact]
|
[ElevatedFact]
|
||||||
public void TestDisableMapping()
|
public void TestDisableMapping()
|
||||||
{
|
{
|
||||||
using TestData data = TestData.Create();
|
using var data = TestData.Create();
|
||||||
|
|
||||||
const string label = "W:";
|
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();
|
mapper.OnWrapperStarted();
|
||||||
Assert.False(Directory.Exists($@"{label}\"));
|
Assert.False(Directory.Exists($@"{label}\"));
|
||||||
|
@ -41,10 +41,10 @@ namespace WinSW.Tests.Extensions
|
||||||
[ElevatedFact]
|
[ElevatedFact]
|
||||||
public void TestMap_PathEndsWithSlash_Throws()
|
public void TestMap_PathEndsWithSlash_Throws()
|
||||||
{
|
{
|
||||||
using TestData data = TestData.Create();
|
using var data = TestData.Create();
|
||||||
|
|
||||||
const string label = "W:";
|
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.ThrowsAny<Exception>(() => mapper.OnWrapperStarted());
|
||||||
Assert.False(Directory.Exists($@"{label}\"));
|
Assert.False(Directory.Exists($@"{label}\"));
|
||||||
|
@ -54,10 +54,10 @@ namespace WinSW.Tests.Extensions
|
||||||
[ElevatedFact]
|
[ElevatedFact]
|
||||||
public void TestMap_LabelDoesNotEndWithColon_Throws()
|
public void TestMap_LabelDoesNotEndWithColon_Throws()
|
||||||
{
|
{
|
||||||
using TestData data = TestData.Create();
|
using var data = TestData.Create();
|
||||||
|
|
||||||
const string label = "W";
|
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.ThrowsAny<Exception>(() => mapper.OnWrapperStarted());
|
||||||
Assert.False(Directory.Exists($@"{label}\"));
|
Assert.False(Directory.Exists($@"{label}\"));
|
||||||
|
@ -82,7 +82,7 @@ namespace WinSW.Tests.Extensions
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
NativeMethods.SHARE_INFO_2 shareInfo = new NativeMethods.SHARE_INFO_2
|
var shareInfo = new NativeMethods.SHARE_INFO_2
|
||||||
{
|
{
|
||||||
netname = name,
|
netname = name,
|
||||||
type = NativeMethods.STYPE_DISKTREE | NativeMethods.STYPE_TEMPORARY,
|
type = NativeMethods.STYPE_DISKTREE | NativeMethods.STYPE_TEMPORARY,
|
||||||
|
|
|
@ -405,7 +405,7 @@ $@"<service>
|
||||||
<arguments>arguments</arguments>
|
<arguments>arguments</arguments>
|
||||||
</service>";
|
</service>";
|
||||||
|
|
||||||
XmlServiceConfig config = XmlServiceConfig.FromXml(seedXml);
|
var config = XmlServiceConfig.FromXml(seedXml);
|
||||||
|
|
||||||
VerifyEqual(prestart, config.Prestart);
|
VerifyEqual(prestart, config.Prestart);
|
||||||
VerifyEqual(poststart, config.Poststart);
|
VerifyEqual(poststart, config.Poststart);
|
||||||
|
|
|
@ -33,11 +33,11 @@ $@"<service>
|
||||||
/// <exception cref="Exception">Command failure</exception>
|
/// <exception cref="Exception">Command failure</exception>
|
||||||
public static string Test(string[] arguments, XmlServiceConfig config = null)
|
public static string Test(string[] arguments, XmlServiceConfig config = null)
|
||||||
{
|
{
|
||||||
TextWriter tmpOut = Console.Out;
|
var tmpOut = Console.Out;
|
||||||
TextWriter tmpError = Console.Error;
|
var tmpError = Console.Error;
|
||||||
|
|
||||||
using StringWriter swOut = new StringWriter();
|
using var swOut = new StringWriter();
|
||||||
using StringWriter swError = new StringWriter();
|
using var swError = new StringWriter();
|
||||||
|
|
||||||
Console.SetOut(swOut);
|
Console.SetOut(swOut);
|
||||||
Console.SetError(swError);
|
Console.SetError(swError);
|
||||||
|
@ -67,11 +67,11 @@ $@"<service>
|
||||||
{
|
{
|
||||||
Exception exception = null;
|
Exception exception = null;
|
||||||
|
|
||||||
TextWriter tmpOut = Console.Out;
|
var tmpOut = Console.Out;
|
||||||
TextWriter tmpError = Console.Error;
|
var tmpError = Console.Error;
|
||||||
|
|
||||||
using StringWriter swOut = new StringWriter();
|
using var swOut = new StringWriter();
|
||||||
using StringWriter swError = new StringWriter();
|
using var swError = new StringWriter();
|
||||||
|
|
||||||
Console.SetOut(swOut);
|
Console.SetOut(swOut);
|
||||||
Console.SetError(swError);
|
Console.SetError(swError);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using WinSW.Tests.Extensions;
|
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
namespace WinSW.Tests.Util
|
namespace WinSW.Tests.Util
|
||||||
|
@ -57,7 +56,7 @@ namespace WinSW.Tests.Util
|
||||||
|
|
||||||
public string ToXmlString(bool dumpConfig = false)
|
public string ToXmlString(bool dumpConfig = false)
|
||||||
{
|
{
|
||||||
StringBuilder str = new StringBuilder();
|
var str = new StringBuilder();
|
||||||
if (this.PrintXmlVersion)
|
if (this.PrintXmlVersion)
|
||||||
{
|
{
|
||||||
// TODO: The encoding is generally wrong
|
// TODO: The encoding is generally wrong
|
||||||
|
@ -121,7 +120,7 @@ namespace WinSW.Tests.Util
|
||||||
|
|
||||||
public ConfigXmlBuilder WithDownload(Download download)
|
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}\"");
|
xml.Append($"<download from=\"{download.From}\" to=\"{download.To}\" failOnError=\"{download.FailOnError}\"");
|
||||||
|
|
||||||
// Authentication
|
// Authentication
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace WinSW.Tests.Util
|
||||||
hr = client.SetEventCallbacks(this);
|
hr = client.SetEventCallbacks(this);
|
||||||
AssertEx.Succeeded(hr);
|
AssertEx.Succeeded(hr);
|
||||||
|
|
||||||
IntPtr pointer = Marshal.GetIUnknownForObject(client);
|
var pointer = Marshal.GetIUnknownForObject(client);
|
||||||
Assert.Equal(1, Marshal.Release(pointer));
|
Assert.Equal(1, Marshal.Release(pointer));
|
||||||
|
|
||||||
target = DataTarget.CreateFromDbgEng(pointer);
|
target = DataTarget.CreateFromDbgEng(pointer);
|
||||||
|
@ -125,7 +125,7 @@ namespace WinSW.Tests.Util
|
||||||
{
|
{
|
||||||
using var runtime = this.target.ClrVersions.Single().CreateRuntime();
|
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 type = module.GetTypeByName(this.trackerType.FullName);
|
||||||
var field = type.GetStaticFieldByName(this.hitsField.Name);
|
var field = type.GetStaticFieldByName(this.hitsField.Name);
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace WinSW.Tests.Util
|
||||||
internal static string NET461Exe => Path.Combine(ArtifactsDirectory, "publish", "WinSW.NET461.exe");
|
internal static string NET461Exe => Path.Combine(ArtifactsDirectory, "publish", "WinSW.NET461.exe");
|
||||||
|
|
||||||
internal static string WinSWExe =>
|
internal static string WinSWExe =>
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
Path.ChangeExtension(typeof(Program).Assembly.Location, ".exe");
|
Path.ChangeExtension(typeof(Program).Assembly.Location, ".exe");
|
||||||
#else
|
#else
|
||||||
typeof(Program).Assembly.Location;
|
typeof(Program).Assembly.Location;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Reflection;
|
using WinSW.Configuration;
|
||||||
using WinSW.Configuration;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace WinSW.Tests.Util
|
namespace WinSW.Tests.Util
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace WinSW.Logging
|
||||||
|
|
||||||
protected override void Append(LoggingEvent loggingEvent)
|
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
|
// We write the event iff the provider is ready
|
||||||
eventLog?.WriteEntry(loggingEvent.RenderedMessage, ToEventLogEntryType(loggingEvent.Level));
|
eventLog?.WriteEntry(loggingEvent.RenderedMessage, ToEventLogEntryType(loggingEvent.Level));
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace WinSW.Logging
|
||||||
{
|
{
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
|
|
||||||
Level level = loggingEvent.Level;
|
var level = loggingEvent.Level;
|
||||||
Console.ForegroundColor =
|
Console.ForegroundColor =
|
||||||
level >= Level.Error ? ConsoleColor.Red :
|
level >= Level.Error ? ConsoleColor.Red :
|
||||||
level >= Level.Warn ? ConsoleColor.Yellow :
|
level >= Level.Warn ? ConsoleColor.Yellow :
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace WinSW
|
||||||
return TestExecutablePath;
|
return TestExecutablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
using Process current = Process.GetCurrentProcess();
|
using var current = Process.GetCurrentProcess();
|
||||||
return current.MainModule!.FileName!;
|
return current.MainModule!.FileName!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ namespace WinSW
|
||||||
Console.SetError(new StreamWriter(stderr) { AutoFlush = true });
|
Console.SetError(new StreamWriter(stderr) { AutoFlush = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
args = args[4..];
|
args = args[4..];
|
||||||
#else
|
#else
|
||||||
string[] oldArgs = args;
|
string[] oldArgs = args;
|
||||||
|
@ -116,15 +116,13 @@ namespace WinSW
|
||||||
XmlServiceConfig config = null!;
|
XmlServiceConfig config = null!;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
config = LoadConfig(pathToConfig);
|
config = LoadConfigAndInitLoggers(pathToConfig, false);
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
Throw.Command.Exception("The specified command or file was not found.");
|
Throw.Command.Exception("The specified command or file was not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
InitLoggers(config, enableConsoleLogging: false);
|
|
||||||
|
|
||||||
Log.Debug("Starting WinSW in service mode.");
|
Log.Debug("Starting WinSW in service mode.");
|
||||||
|
|
||||||
AutoRefresh(config);
|
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)) ||
|
if (principal.IsInRole(new SecurityIdentifier(WellKnownSidType.ServiceSid, null)) ||
|
||||||
principal.IsInRole(new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null)) ||
|
principal.IsInRole(new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null)) ||
|
||||||
principal.IsInRole(new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null)) ||
|
principal.IsInRole(new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null)) ||
|
||||||
|
@ -420,8 +418,7 @@ namespace WinSW
|
||||||
|
|
||||||
void Install(string? pathToConfig, bool noElevate, string? username, string? password)
|
void Install(string? pathToConfig, bool noElevate, string? username, string? password)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
InitLoggers(config, enableConsoleLogging: true);
|
|
||||||
|
|
||||||
if (!elevated)
|
if (!elevated)
|
||||||
{
|
{
|
||||||
|
@ -431,7 +428,7 @@ namespace WinSW
|
||||||
|
|
||||||
Log.Info($"Installing service '{config.Format()}'...");
|
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))
|
if (scm.ServiceExists(config.Name))
|
||||||
{
|
{
|
||||||
|
@ -468,7 +465,7 @@ namespace WinSW
|
||||||
Security.AddServiceLogonRight(ref username);
|
Security.AddServiceLogonRight(ref username);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Service sc = scm.CreateService(
|
using var sc = scm.CreateService(
|
||||||
config.Name,
|
config.Name,
|
||||||
config.DisplayName,
|
config.DisplayName,
|
||||||
config.StartMode,
|
config.StartMode,
|
||||||
|
@ -483,7 +480,7 @@ namespace WinSW
|
||||||
sc.SetDescription(description);
|
sc.SetDescription(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_ACTION[] actions = config.FailureActions;
|
var actions = config.FailureActions;
|
||||||
if (actions.Length > 0)
|
if (actions.Length > 0)
|
||||||
{
|
{
|
||||||
sc.SetFailureActions(config.ResetFailureAfter, actions);
|
sc.SetFailureActions(config.ResetFailureAfter, actions);
|
||||||
|
@ -545,8 +542,7 @@ namespace WinSW
|
||||||
|
|
||||||
void Uninstall(string? pathToConfig, bool noElevate)
|
void Uninstall(string? pathToConfig, bool noElevate)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
InitLoggers(config, enableConsoleLogging: true);
|
|
||||||
|
|
||||||
if (!elevated)
|
if (!elevated)
|
||||||
{
|
{
|
||||||
|
@ -556,10 +552,10 @@ namespace WinSW
|
||||||
|
|
||||||
Log.Info($"Uninstalling service '{config.Format()}'...");
|
Log.Info($"Uninstalling service '{config.Format()}'...");
|
||||||
|
|
||||||
using ServiceManager scm = ServiceManager.Open(ServiceManagerAccess.Connect);
|
using var scm = ServiceManager.Open(ServiceManagerAccess.Connect);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using Service sc = scm.OpenService(config.Name);
|
using var sc = scm.OpenService(config.Name);
|
||||||
|
|
||||||
if (sc.Status != ServiceControllerStatus.Stopped)
|
if (sc.Status != ServiceControllerStatus.Stopped)
|
||||||
{
|
{
|
||||||
|
@ -595,8 +591,7 @@ namespace WinSW
|
||||||
|
|
||||||
void Start(string? pathToConfig, bool noElevate, bool noWait, CancellationToken ct)
|
void Start(string? pathToConfig, bool noElevate, bool noWait, CancellationToken ct)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
InitLoggers(config, enableConsoleLogging: true);
|
|
||||||
|
|
||||||
if (!elevated)
|
if (!elevated)
|
||||||
{
|
{
|
||||||
|
@ -641,8 +636,7 @@ namespace WinSW
|
||||||
|
|
||||||
void Stop(string? pathToConfig, bool noElevate, bool noWait, bool force, CancellationToken ct)
|
void Stop(string? pathToConfig, bool noElevate, bool noWait, bool force, CancellationToken ct)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
InitLoggers(config, enableConsoleLogging: true);
|
|
||||||
|
|
||||||
if (!elevated)
|
if (!elevated)
|
||||||
{
|
{
|
||||||
|
@ -695,8 +689,7 @@ namespace WinSW
|
||||||
|
|
||||||
void Restart(string? pathToConfig, bool noElevate, bool force, CancellationToken ct)
|
void Restart(string? pathToConfig, bool noElevate, bool force, CancellationToken ct)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
InitLoggers(config, enableConsoleLogging: true);
|
|
||||||
|
|
||||||
if (!elevated)
|
if (!elevated)
|
||||||
{
|
{
|
||||||
|
@ -758,7 +751,7 @@ namespace WinSW
|
||||||
|
|
||||||
if (startedDependentServices != null)
|
if (startedDependentServices != null)
|
||||||
{
|
{
|
||||||
foreach (ServiceController service in startedDependentServices)
|
foreach (var service in startedDependentServices)
|
||||||
{
|
{
|
||||||
if (service.Status == ServiceControllerStatus.Stopped)
|
if (service.Status == ServiceControllerStatus.Stopped)
|
||||||
{
|
{
|
||||||
|
@ -773,8 +766,7 @@ namespace WinSW
|
||||||
|
|
||||||
void RestartSelf(string? pathToConfig)
|
void RestartSelf(string? pathToConfig)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
InitLoggers(config, enableConsoleLogging: true);
|
|
||||||
|
|
||||||
if (!elevated)
|
if (!elevated)
|
||||||
{
|
{
|
||||||
|
@ -794,7 +786,7 @@ namespace WinSW
|
||||||
IntPtr.Zero,
|
IntPtr.Zero,
|
||||||
null,
|
null,
|
||||||
default,
|
default,
|
||||||
out ProcessApis.PROCESS_INFORMATION processInfo))
|
out var processInfo))
|
||||||
{
|
{
|
||||||
Throw.Command.Win32Exception("Failed to invoke restart.");
|
Throw.Command.Win32Exception("Failed to invoke restart.");
|
||||||
}
|
}
|
||||||
|
@ -805,8 +797,7 @@ namespace WinSW
|
||||||
|
|
||||||
static int Status(string? pathToConfig)
|
static int Status(string? pathToConfig)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
InitLoggers(config, enableConsoleLogging: true);
|
|
||||||
|
|
||||||
using var svc = new ServiceController(config.Name);
|
using var svc = new ServiceController(config.Name);
|
||||||
try
|
try
|
||||||
|
@ -838,8 +829,7 @@ namespace WinSW
|
||||||
|
|
||||||
void Test(string? pathToConfig, bool noElevate, bool noBreak)
|
void Test(string? pathToConfig, bool noElevate, bool noBreak)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
InitLoggers(config, enableConsoleLogging: true);
|
|
||||||
|
|
||||||
if (!elevated)
|
if (!elevated)
|
||||||
{
|
{
|
||||||
|
@ -849,7 +839,7 @@ namespace WinSW
|
||||||
|
|
||||||
AutoRefresh(config);
|
AutoRefresh(config);
|
||||||
|
|
||||||
using WrapperService wsvc = new WrapperService(config);
|
using var wsvc = new WrapperService(config);
|
||||||
wsvc.RaiseOnStart(args);
|
wsvc.RaiseOnStart(args);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -860,7 +850,7 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using ManualResetEvent evt = new ManualResetEvent(false);
|
using var evt = new ManualResetEvent(false);
|
||||||
|
|
||||||
Console.WriteLine("Press Ctrl+C to stop the service...");
|
Console.WriteLine("Press Ctrl+C to stop the service...");
|
||||||
Console.CancelKeyPress += CancelKeyPress;
|
Console.CancelKeyPress += CancelKeyPress;
|
||||||
|
@ -883,8 +873,7 @@ namespace WinSW
|
||||||
|
|
||||||
void Refresh(string? pathToConfig, bool noElevate)
|
void Refresh(string? pathToConfig, bool noElevate)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
InitLoggers(config, enableConsoleLogging: true);
|
|
||||||
|
|
||||||
if (!elevated)
|
if (!elevated)
|
||||||
{
|
{
|
||||||
|
@ -900,7 +889,7 @@ namespace WinSW
|
||||||
if (all)
|
if (all)
|
||||||
{
|
{
|
||||||
using var scm = ServiceManager.Open(ServiceManagerAccess.EnumerateService);
|
using var scm = ServiceManager.Open(ServiceManagerAccess.EnumerateService);
|
||||||
(IntPtr services, int count) = scm.EnumerateServices();
|
(var services, int count) = scm.EnumerateServices();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int prevProcessId = -1;
|
int prevProcessId = -1;
|
||||||
|
@ -915,7 +904,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
if (prevProcessId >= 0)
|
if (prevProcessId >= 0)
|
||||||
{
|
{
|
||||||
using Process process = Process.GetProcessById(prevProcessId);
|
using var process = Process.GetProcessById(prevProcessId);
|
||||||
Draw(process, string.Empty, false);
|
Draw(process, string.Empty, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -926,7 +915,7 @@ namespace WinSW
|
||||||
|
|
||||||
if (prevProcessId >= 0)
|
if (prevProcessId >= 0)
|
||||||
{
|
{
|
||||||
using Process process = Process.GetProcessById(prevProcessId);
|
using var process = Process.GetProcessById(prevProcessId);
|
||||||
Draw(process, string.Empty, true);
|
Draw(process, string.Empty, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -937,15 +926,15 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
|
|
||||||
using ServiceManager scm = ServiceManager.Open(ServiceManagerAccess.Connect);
|
using var scm = ServiceManager.Open(ServiceManagerAccess.Connect);
|
||||||
using Service sc = scm.OpenService(config.Name, ServiceAccess.QueryStatus);
|
using var sc = scm.OpenService(config.Name, ServiceAccess.QueryStatus);
|
||||||
|
|
||||||
int processId = sc.ProcessId;
|
int processId = sc.ProcessId;
|
||||||
if (processId >= 0)
|
if (processId >= 0)
|
||||||
{
|
{
|
||||||
using Process process = Process.GetProcessById(processId);
|
using var process = Process.GetProcessById(processId);
|
||||||
Draw(process, string.Empty, true);
|
Draw(process, string.Empty, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -972,11 +961,11 @@ namespace WinSW
|
||||||
|
|
||||||
Console.WriteLine(process.Format());
|
Console.WriteLine(process.Format());
|
||||||
|
|
||||||
List<Process> children = process.GetChildren();
|
var children = process.GetChildren();
|
||||||
int count = children.Count;
|
int count = children.Count;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
using Process child = children[i];
|
using var child = children[i];
|
||||||
Draw(child, indentation, i == count - 1);
|
Draw(child, indentation, i == count - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -984,7 +973,7 @@ namespace WinSW
|
||||||
|
|
||||||
void DevKill(string? pathToConfig, bool noElevate)
|
void DevKill(string? pathToConfig, bool noElevate)
|
||||||
{
|
{
|
||||||
XmlServiceConfig config = LoadConfig(pathToConfig);
|
var config = LoadConfigAndInitLoggers(pathToConfig, true);
|
||||||
|
|
||||||
if (!elevated)
|
if (!elevated)
|
||||||
{
|
{
|
||||||
|
@ -992,13 +981,13 @@ namespace WinSW
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using ServiceManager scm = ServiceManager.Open();
|
using var scm = ServiceManager.Open();
|
||||||
using Service sc = scm.OpenService(config.Name);
|
using var sc = scm.OpenService(config.Name);
|
||||||
|
|
||||||
int processId = sc.ProcessId;
|
int processId = sc.ProcessId;
|
||||||
if (processId >= 0)
|
if (processId >= 0)
|
||||||
{
|
{
|
||||||
using Process process = Process.GetProcessById(processId);
|
using var process = Process.GetProcessById(processId);
|
||||||
|
|
||||||
process.StopDescendants(config.StopTimeoutInMs);
|
process.StopDescendants(config.StopTimeoutInMs);
|
||||||
}
|
}
|
||||||
|
@ -1007,7 +996,7 @@ namespace WinSW
|
||||||
static unsafe void DevList()
|
static unsafe void DevList()
|
||||||
{
|
{
|
||||||
using var scm = ServiceManager.Open(ServiceManagerAccess.EnumerateService);
|
using var scm = ServiceManager.Open(ServiceManagerAccess.EnumerateService);
|
||||||
(IntPtr services, int count) = scm.EnumerateServices();
|
(var services, int count) = scm.EnumerateServices();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
|
@ -1058,7 +1047,7 @@ namespace WinSW
|
||||||
" " + (stderrName ?? NoPipe) +
|
" " + (stderrName ?? NoPipe) +
|
||||||
commandLine.Remove(commandLine.IndexOf(exe), exe.Length).TrimStart('"');
|
commandLine.Remove(commandLine.IndexOf(exe), exe.Length).TrimStart('"');
|
||||||
|
|
||||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
var startInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
UseShellExecute = true,
|
UseShellExecute = true,
|
||||||
Verb = "runas",
|
Verb = "runas",
|
||||||
|
@ -1069,7 +1058,7 @@ namespace WinSW
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using Process elevated = Process.Start(startInfo)!;
|
using var elevated = Process.Start(startInfo)!;
|
||||||
|
|
||||||
if (stdinName is not null)
|
if (stdinName is not null)
|
||||||
{
|
{
|
||||||
|
@ -1106,9 +1095,9 @@ namespace WinSW
|
||||||
return;
|
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("SYSTEM")?
|
||||||
.OpenSubKey("CurrentControlSet")?
|
.OpenSubKey("CurrentControlSet")?
|
||||||
.OpenSubKey("Services")?
|
.OpenSubKey("Services")?
|
||||||
|
@ -1119,7 +1108,7 @@ namespace WinSW
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime registryLastWriteTime = registryKey.GetLastWriteTime();
|
var registryLastWriteTime = registryKey.GetLastWriteTime();
|
||||||
|
|
||||||
if (fileLastWriteTime > registryLastWriteTime)
|
if (fileLastWriteTime > registryLastWriteTime)
|
||||||
{
|
{
|
||||||
|
@ -1129,16 +1118,16 @@ namespace WinSW
|
||||||
|
|
||||||
static void DoRefresh(XmlServiceConfig config)
|
static void DoRefresh(XmlServiceConfig config)
|
||||||
{
|
{
|
||||||
using ServiceManager scm = ServiceManager.Open(ServiceManagerAccess.Connect);
|
using var scm = ServiceManager.Open(ServiceManagerAccess.Connect);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using Service sc = scm.OpenService(config.Name);
|
using var sc = scm.OpenService(config.Name);
|
||||||
|
|
||||||
sc.ChangeConfig(config.DisplayName, config.StartMode, config.ServiceDependencies);
|
sc.ChangeConfig(config.DisplayName, config.StartMode, config.ServiceDependencies);
|
||||||
|
|
||||||
sc.SetDescription(config.Description);
|
sc.SetDescription(config.Description);
|
||||||
|
|
||||||
SC_ACTION[] actions = config.FailureActions;
|
var actions = config.FailureActions;
|
||||||
if (actions.Length > 0)
|
if (actions.Length > 0)
|
||||||
{
|
{
|
||||||
sc.SetFailureActions(config.ResetFailureAfter, actions);
|
sc.SetFailureActions(config.ResetFailureAfter, actions);
|
||||||
|
@ -1173,42 +1162,54 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <exception cref="FileNotFoundException" />
|
/// <exception cref="FileNotFoundException" />
|
||||||
private static XmlServiceConfig LoadConfig(string? path)
|
private static XmlServiceConfig LoadConfigAndInitLoggers(string? path, bool enableConsoleLogging)
|
||||||
{
|
{
|
||||||
if (TestConfig != null)
|
if (TestConfig != null)
|
||||||
{
|
{
|
||||||
return TestConfig;
|
return TestConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path != null)
|
|
||||||
{
|
|
||||||
return new XmlServiceConfig(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InitLoggers(XmlServiceConfig config, bool enableConsoleLogging)
|
|
||||||
{
|
|
||||||
if (XmlServiceConfig.TestConfig != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make logging levels configurable
|
// TODO: Make logging levels configurable
|
||||||
Level fileLogLevel = Level.Debug;
|
var fileLogLevel = Level.Debug;
|
||||||
|
|
||||||
// TODO: Debug should not be printed to console by default. Otherwise commands like 'status' will be pollutted
|
// 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
|
// This is a workaround till there is a better command line parsing, which will allow determining
|
||||||
Level consoleLogLevel = Level.Info;
|
var consoleLogLevel = Level.Info;
|
||||||
Level eventLogLevel = Level.Warn;
|
var eventLogLevel = Level.Warn;
|
||||||
|
|
||||||
List<IAppender> appenders = new List<IAppender>();
|
// console log
|
||||||
|
if (enableConsoleLogging)
|
||||||
|
{
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
config = new XmlServiceConfig(path);
|
||||||
|
}
|
||||||
|
|
||||||
// .wrapper.log
|
// .wrapper.log
|
||||||
string wrapperLogPath = Path.Combine(config.LogDirectory, config.BaseName + ".wrapper.log");
|
string wrapperLogPath = Path.Combine(config.LogDirectory, config.BaseName + ".wrapper.log");
|
||||||
|
@ -1223,20 +1224,6 @@ namespace WinSW
|
||||||
Layout = new PatternLayout("%date %-5level - %message%newline"),
|
Layout = new PatternLayout("%date %-5level - %message%newline"),
|
||||||
};
|
};
|
||||||
wrapperLog.ActivateOptions();
|
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
|
// event log
|
||||||
var systemEventLogger = new ServiceEventLogAppender(WrapperService.eventLogProvider)
|
var systemEventLogger = new ServiceEventLogAppender(WrapperService.eventLogProvider)
|
||||||
|
@ -1245,20 +1232,22 @@ namespace WinSW
|
||||||
Threshold = eventLogLevel,
|
Threshold = eventLogLevel,
|
||||||
};
|
};
|
||||||
systemEventLogger.ActivateOptions();
|
systemEventLogger.ActivateOptions();
|
||||||
appenders.Add(systemEventLogger);
|
|
||||||
|
|
||||||
BasicConfigurator.Configure(
|
BasicConfigurator.Configure(
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
LogManager.GetRepository(System.Reflection.Assembly.GetExecutingAssembly()),
|
LogManager.GetRepository(Assembly.GetExecutingAssembly()),
|
||||||
#endif
|
#endif
|
||||||
appenders.ToArray());
|
wrapperLog,
|
||||||
|
systemEventLogger);
|
||||||
|
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <exception cref="CommandException" />
|
/// <exception cref="CommandException" />
|
||||||
internal static bool IsProcessElevated()
|
internal static bool IsProcessElevated()
|
||||||
{
|
{
|
||||||
IntPtr process = ProcessApis.GetCurrentProcess();
|
var process = ProcessApis.GetCurrentProcess();
|
||||||
if (!ProcessApis.OpenProcessToken(process, TokenAccessLevels.Read, out IntPtr token))
|
if (!ProcessApis.OpenProcessToken(process, TokenAccessLevels.Read, out var token))
|
||||||
{
|
{
|
||||||
Throw.Command.Win32Exception("Failed to open process token.");
|
Throw.Command.Win32Exception("Failed to open process token.");
|
||||||
}
|
}
|
||||||
|
@ -1270,7 +1259,7 @@ namespace WinSW
|
||||||
if (!SecurityApis.GetTokenInformation(
|
if (!SecurityApis.GetTokenInformation(
|
||||||
token,
|
token,
|
||||||
SecurityApis.TOKEN_INFORMATION_CLASS.TokenElevation,
|
SecurityApis.TOKEN_INFORMATION_CLASS.TokenElevation,
|
||||||
out SecurityApis.TOKEN_ELEVATION elevation,
|
out var elevation,
|
||||||
sizeof(SecurityApis.TOKEN_ELEVATION),
|
sizeof(SecurityApis.TOKEN_ELEVATION),
|
||||||
out _))
|
out _))
|
||||||
{
|
{
|
||||||
|
@ -1288,10 +1277,10 @@ namespace WinSW
|
||||||
|
|
||||||
private static string ReadPassword()
|
private static string ReadPassword()
|
||||||
{
|
{
|
||||||
StringBuilder buf = new StringBuilder();
|
var buf = new StringBuilder();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
ConsoleKeyInfo key = Console.ReadKey(true);
|
var key = Console.ReadKey(true);
|
||||||
if (key.Key == ConsoleKey.Enter)
|
if (key.Key == ConsoleKey.Enter)
|
||||||
{
|
{
|
||||||
return buf.ToString();
|
return buf.ToString();
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace WinSW
|
||||||
/// <exception cref="TimeoutException" />
|
/// <exception cref="TimeoutException" />
|
||||||
internal static void WaitForStatus(this ServiceController serviceController, ServiceControllerStatus desiredStatus, ServiceControllerStatus pendingStatus, CancellationToken ct)
|
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 (; ; )
|
for (; ; )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace WinSW
|
||||||
private static readonly int additionalStopTimeout = 1_000;
|
private static readonly int additionalStopTimeout = 1_000;
|
||||||
|
|
||||||
private static readonly ILog Log = LogManager.GetLogger(
|
private static readonly ILog Log = LogManager.GetLogger(
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
Assembly.GetExecutingAssembly(),
|
Assembly.GetExecutingAssembly(),
|
||||||
#endif
|
#endif
|
||||||
"WinSW");
|
"WinSW");
|
||||||
|
@ -71,7 +71,7 @@ namespace WinSW
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void HandleFileCopies()
|
private void HandleFileCopies()
|
||||||
{
|
{
|
||||||
var file = this.config.BasePath + ".copies";
|
string? file = this.config.BasePath + ".copies";
|
||||||
if (!File.Exists(file))
|
if (!File.Exists(file))
|
||||||
{
|
{
|
||||||
return; // nothing to handle
|
return; // nothing to handle
|
||||||
|
@ -128,7 +128,7 @@ namespace WinSW
|
||||||
Directory.CreateDirectory(logDirectory);
|
Directory.CreateDirectory(logDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogHandler logAppender = this.config.LogHandler;
|
var logAppender = this.config.LogHandler;
|
||||||
logAppender.EventLogger = this;
|
logAppender.EventLogger = this;
|
||||||
return logAppender;
|
return logAppender;
|
||||||
}
|
}
|
||||||
|
@ -264,11 +264,11 @@ namespace WinSW
|
||||||
this.HandleFileCopies();
|
this.HandleFileCopies();
|
||||||
|
|
||||||
// handle downloads
|
// handle downloads
|
||||||
List<Download> downloads = this.config.Downloads;
|
var downloads = this.config.Downloads;
|
||||||
Task[] tasks = new Task[downloads.Count];
|
var tasks = new Task[downloads.Count];
|
||||||
for (int i = 0; i < downloads.Count; i++)
|
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()}";
|
string downloadMessage = $"Downloading: {download.From} to {download.To}. failOnError={download.FailOnError.ToString()}";
|
||||||
Log.Info(downloadMessage);
|
Log.Info(downloadMessage);
|
||||||
tasks[i] = download.PerformAsync();
|
tasks[i] = download.PerformAsync();
|
||||||
|
@ -280,14 +280,14 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
catch (AggregateException e)
|
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++)
|
for (int i = 0; i < tasks.Length; i++)
|
||||||
{
|
{
|
||||||
if (tasks[i].IsFaulted)
|
if (tasks[i].IsFaulted)
|
||||||
{
|
{
|
||||||
Download download = downloads[i];
|
var download = downloads[i];
|
||||||
string errorMessage = $"Failed to download {download.From} to {download.To}";
|
string errorMessage = $"Failed to download {download.From} to {download.To}";
|
||||||
AggregateException exception = tasks[i].Exception!;
|
var exception = tasks[i].Exception!;
|
||||||
Log.Error(errorMessage, exception);
|
Log.Error(errorMessage, exception);
|
||||||
|
|
||||||
// TODO: move this code into the download logic
|
// TODO: move this code into the download logic
|
||||||
|
@ -301,13 +301,13 @@ namespace WinSW
|
||||||
throw new AggregateException(exceptions);
|
throw new AggregateException(exceptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessCommand prestart = this.config.Prestart;
|
var prestart = this.config.Prestart;
|
||||||
string? prestartExecutable = prestart.Executable;
|
string? prestartExecutable = prestart.Executable;
|
||||||
if (prestartExecutable != null)
|
if (prestartExecutable != null)
|
||||||
{
|
{
|
||||||
try
|
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.WaitForProcessToExit(process);
|
||||||
this.LogExited($"Pre-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
this.LogExited($"Pre-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
||||||
process.StopDescendants(additionalStopTimeout);
|
process.StopDescendants(additionalStopTimeout);
|
||||||
|
@ -326,17 +326,17 @@ namespace WinSW
|
||||||
this.ExtensionManager.LoadExtensions();
|
this.ExtensionManager.LoadExtensions();
|
||||||
this.ExtensionManager.FireOnWrapperStarted();
|
this.ExtensionManager.FireOnWrapperStarted();
|
||||||
|
|
||||||
LogHandler executableLogHandler = this.CreateExecutableLogHandler();
|
var executableLogHandler = this.CreateExecutableLogHandler();
|
||||||
this.process = this.StartProcess(this.config.Executable, startArguments, executableLogHandler, this.OnMainProcessExited);
|
this.process = this.StartProcess(this.config.Executable, startArguments, executableLogHandler, this.OnMainProcessExited);
|
||||||
this.ExtensionManager.FireOnProcessStarted(this.process);
|
this.ExtensionManager.FireOnProcessStarted(this.process);
|
||||||
|
|
||||||
ProcessCommand poststart = this.config.Poststart;
|
var poststart = this.config.Poststart;
|
||||||
string? poststartExecutable = poststart.Executable;
|
string? poststartExecutable = poststart.Executable;
|
||||||
if (poststartExecutable != null)
|
if (poststartExecutable != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using Process process = StartProcessLocked();
|
using var process = StartProcessLocked();
|
||||||
this.WaitForProcessToExit(process);
|
this.WaitForProcessToExit(process);
|
||||||
this.LogExited($"Post-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
this.LogExited($"Post-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
||||||
process.StopDescendants(additionalStopTimeout);
|
process.StopDescendants(additionalStopTimeout);
|
||||||
|
@ -362,13 +362,13 @@ namespace WinSW
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void DoStop()
|
private void DoStop()
|
||||||
{
|
{
|
||||||
ProcessCommand prestop = this.config.Prestop;
|
var prestop = this.config.Prestop;
|
||||||
string? prestopExecutable = prestop.Executable;
|
string? prestopExecutable = prestop.Executable;
|
||||||
if (prestopExecutable != null)
|
if (prestopExecutable != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using Process process = StartProcessLocked(prestopExecutable, prestop.Arguments, prestop.CreateLogHandler());
|
using var process = StartProcessLocked(prestopExecutable, prestop.Arguments, prestop.CreateLogHandler());
|
||||||
this.WaitForProcessToExit(process);
|
this.WaitForProcessToExit(process);
|
||||||
this.LogExited($"Pre-stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
this.LogExited($"Pre-stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
||||||
process.StopDescendants(additionalStopTimeout);
|
process.StopDescendants(additionalStopTimeout);
|
||||||
|
@ -387,7 +387,7 @@ namespace WinSW
|
||||||
string? stopArguments = this.config.StopArguments;
|
string? stopArguments = this.config.StopArguments;
|
||||||
if (stopExecutable is null && stopArguments is null)
|
if (stopExecutable is null && stopArguments is null)
|
||||||
{
|
{
|
||||||
Process process = this.process;
|
var process = this.process;
|
||||||
Log.Debug("ProcessKill " + process.Id);
|
Log.Debug("ProcessKill " + process.Id);
|
||||||
bool? result = process.Stop(this.config.StopTimeoutInMs);
|
bool? result = process.Stop(this.config.StopTimeoutInMs);
|
||||||
this.LogMinimal($"Child process '{process.Format()}' " + result switch
|
this.LogMinimal($"Child process '{process.Format()}' " + result switch
|
||||||
|
@ -408,7 +408,7 @@ namespace WinSW
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO: Redirect logging to Log4Net once https://github.com/kohsuke/winsw/pull/213 is integrated
|
// 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);
|
Log.Debug("WaitForProcessToExit " + this.process.Id + "+" + stopProcess.Id);
|
||||||
this.WaitForProcessToExit(stopProcess);
|
this.WaitForProcessToExit(stopProcess);
|
||||||
|
@ -425,13 +425,13 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessCommand poststop = this.config.Poststop;
|
var poststop = this.config.Poststop;
|
||||||
string? poststopExecutable = poststop.Executable;
|
string? poststopExecutable = poststop.Executable;
|
||||||
if (poststopExecutable != null)
|
if (poststopExecutable != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using Process process = StartProcessLocked(poststopExecutable, poststop.Arguments, poststop.CreateLogHandler());
|
using var process = StartProcessLocked(poststopExecutable, poststop.Arguments, poststop.CreateLogHandler());
|
||||||
this.WaitForProcessToExit(process);
|
this.WaitForProcessToExit(process);
|
||||||
this.LogExited($"Post-Stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
this.LogExited($"Post-Stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
||||||
process.StopDescendants(additionalStopTimeout);
|
process.StopDescendants(additionalStopTimeout);
|
||||||
|
@ -477,13 +477,13 @@ namespace WinSW
|
||||||
private void AcceptPreshutdown()
|
private void AcceptPreshutdown()
|
||||||
{
|
{
|
||||||
const string acceptedCommandsFieldName =
|
const string acceptedCommandsFieldName =
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
"_acceptedCommands";
|
"_acceptedCommands";
|
||||||
#else
|
#else
|
||||||
"acceptedCommands";
|
"acceptedCommands";
|
||||||
#endif
|
#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)
|
if (acceptedCommandsField is null)
|
||||||
{
|
{
|
||||||
throw new MissingFieldException(nameof(ServiceBase), acceptedCommandsFieldName);
|
throw new MissingFieldException(nameof(ServiceBase), acceptedCommandsFieldName);
|
||||||
|
@ -501,8 +501,8 @@ namespace WinSW
|
||||||
|
|
||||||
private void SignalStopped()
|
private void SignalStopped()
|
||||||
{
|
{
|
||||||
using ServiceManager scm = ServiceManager.Open();
|
using var scm = ServiceManager.Open();
|
||||||
using Service sc = scm.OpenService(this.ServiceName, ServiceApis.ServiceAccess.QueryStatus);
|
using var sc = scm.OpenService(this.ServiceName, ServiceApis.ServiceAccess.QueryStatus);
|
||||||
|
|
||||||
sc.SetStatus(this.ServiceHandle, ServiceControllerStatus.Stopped);
|
sc.SetStatus(this.ServiceHandle, ServiceControllerStatus.Stopped);
|
||||||
}
|
}
|
||||||
|
@ -549,16 +549,16 @@ namespace WinSW
|
||||||
RedirectStandardError = logHandler?.ErrFileDisabled == false,
|
RedirectStandardError = logHandler?.ErrFileDisabled == false,
|
||||||
};
|
};
|
||||||
|
|
||||||
Dictionary<string, string> environment = this.config.EnvironmentVariables;
|
var environment = this.config.EnvironmentVariables;
|
||||||
if (environment.Count > 0)
|
if (environment.Count > 0)
|
||||||
{
|
{
|
||||||
var newEnvironment =
|
var newEnvironment =
|
||||||
#if NETCOREAPP
|
#if NET
|
||||||
startInfo.Environment;
|
startInfo.Environment;
|
||||||
#else
|
#else
|
||||||
startInfo.EnvironmentVariables;
|
startInfo.EnvironmentVariables;
|
||||||
#endif
|
#endif
|
||||||
foreach (KeyValuePair<string, string> pair in environment)
|
foreach (var pair in environment)
|
||||||
{
|
{
|
||||||
newEnvironment[pair.Key] = pair.Value;
|
newEnvironment[pair.Key] = pair.Value;
|
||||||
}
|
}
|
||||||
|
@ -607,7 +607,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
process.Exited += (sender, _) =>
|
process.Exited += (sender, _) =>
|
||||||
{
|
{
|
||||||
Process process = (Process)sender!;
|
var process = (Process)sender!;
|
||||||
|
|
||||||
if (!process.EnableRaisingEvents)
|
if (!process.EnableRaisingEvents)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue