mirror of https://github.com/winsw/winsw
Style updates (#735)
parent
820f46e6bf
commit
1bd0c56a09
|
@ -62,7 +62,7 @@ namespace WinSW.Configuration
|
||||||
public bool Interactive => false;
|
public bool Interactive => false;
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
public Log Log { get => new LogDefaults(); }
|
public Log Log => new LogDefaults();
|
||||||
|
|
||||||
public string LogDirectory => DefaultLogSettings.Directory;
|
public string LogDirectory => DefaultLogSettings.Directory;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ namespace WinSW.Configuration
|
||||||
|
|
||||||
public string ErrFilePattern => this.Log.ErrFilePattern;
|
public string ErrFilePattern => this.Log.ErrFilePattern;
|
||||||
|
|
||||||
public ServiceAccount ServiceAccount => new ServiceAccount()
|
public ServiceAccount ServiceAccount => new()
|
||||||
{
|
{
|
||||||
ServiceAccountName = null,
|
ServiceAccountName = null,
|
||||||
ServiceAccountDomain = null,
|
ServiceAccountDomain = null,
|
||||||
|
@ -108,13 +108,13 @@ namespace WinSW.Configuration
|
||||||
|
|
||||||
public override int? Period => 1;
|
public override int? Period => 1;
|
||||||
|
|
||||||
public override bool OutFileDisabled { get => false; }
|
public override bool OutFileDisabled => false;
|
||||||
|
|
||||||
public override bool ErrFileDisabled { get => false; }
|
public override bool ErrFileDisabled => false;
|
||||||
|
|
||||||
public override string OutFilePattern { get => ".out.log"; }
|
public override string OutFilePattern => ".out.log";
|
||||||
|
|
||||||
public override string ErrFilePattern { get => ".err.log"; }
|
public override string ErrFilePattern => ".err.log";
|
||||||
|
|
||||||
public override string? AutoRollAtTime => null;
|
public override string? AutoRollAtTime => null;
|
||||||
|
|
||||||
|
@ -125,9 +125,9 @@ namespace WinSW.Configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Environment
|
// Environment
|
||||||
public List<Download> Downloads => new List<Download>(0);
|
public List<Download> Downloads => new(0);
|
||||||
|
|
||||||
public Dictionary<string, string> EnvironmentVariables => new Dictionary<string, string>(0);
|
public Dictionary<string, string> EnvironmentVariables => new(0);
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
public bool BeepOnShutdown => false;
|
public bool BeepOnShutdown => false;
|
||||||
|
@ -135,7 +135,7 @@ namespace WinSW.Configuration
|
||||||
// Extensions
|
// Extensions
|
||||||
public XmlNode? ExtensionsConfiguration => null;
|
public XmlNode? ExtensionsConfiguration => null;
|
||||||
|
|
||||||
public List<YamlExtensionConfiguration>? YamlExtensionsConfiguration => new List<YamlExtensionConfiguration>(0);
|
public List<YamlExtensionConfiguration>? YamlExtensionsConfiguration => new(0);
|
||||||
|
|
||||||
public string BaseName
|
public string BaseName
|
||||||
{
|
{
|
||||||
|
@ -160,7 +160,7 @@ namespace WinSW.Configuration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> ExtensionIds => new List<string>(0);
|
public List<string> ExtensionIds => new(0);
|
||||||
|
|
||||||
public string? SecurityDescriptor => null;
|
public string? SecurityDescriptor => null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace WinSW.Configuration
|
||||||
if (this.AutoRollAtTime != null)
|
if (this.AutoRollAtTime != null)
|
||||||
{
|
{
|
||||||
// validate it
|
// validate it
|
||||||
if (!TimeSpan.TryParse(this.AutoRollAtTime, out TimeSpan autoRollAtTimeValue))
|
if (!TimeSpan.TryParse(this.AutoRollAtTime, 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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,10 +287,8 @@ namespace WinSW.Configuration
|
||||||
{
|
{
|
||||||
if (!int.TryParse(this.ZipOlderThanNumDaysYamlLog, out int zipolderthannumdaysValue))
|
if (!int.TryParse(this.ZipOlderThanNumDaysYamlLog, out int zipolderthannumdaysValue))
|
||||||
{
|
{
|
||||||
// FIXME: Remove the build env specific warning suppression from the codebase
|
// FIXME: Remove the build env specific warning suppression from the codebase
|
||||||
#pragma warning disable S2372 // Exceptions should not be thrown from property getters
|
|
||||||
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but zipOlderThanNumDays does not match the int format found in configuration XML.");
|
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but zipOlderThanNumDays does not match the int format found in configuration XML.");
|
||||||
#pragma warning restore S2372 // Exceptions should not be thrown from property getters
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zipolderthannumdays = zipolderthannumdaysValue;
|
zipolderthannumdays = zipolderthannumdaysValue;
|
||||||
|
@ -356,7 +354,7 @@ namespace WinSW.Configuration
|
||||||
return AuthType.None;
|
return AuthType.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
var auth = ExpandEnv(this.AuthYamlDownload);
|
string auth = ExpandEnv(this.AuthYamlDownload);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -388,7 +386,7 @@ namespace WinSW.Configuration
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
SC_ACTION_TYPE actionType = this.FailureAction switch
|
var actionType = this.FailureAction 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,
|
||||||
|
@ -493,7 +491,7 @@ namespace WinSW.Configuration
|
||||||
return this.Defaults.StartMode;
|
return this.Defaults.StartMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
var p = ExpandEnv(this.StartModeYaml);
|
string p = ExpandEnv(this.StartModeYaml);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -516,7 +514,7 @@ namespace WinSW.Configuration
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var args = this.GetArguments(this.ArgumentsYaml, ArgType.Arg);
|
string? args = this.GetArguments(this.ArgumentsYaml, ArgType.Arg);
|
||||||
return args is null ? this.Defaults.Arguments : args;
|
return args is null ? this.Defaults.Arguments : args;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,7 +570,7 @@ namespace WinSW.Configuration
|
||||||
return this.Defaults.Priority;
|
return this.Defaults.Priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
var p = ExpandEnv(this.PriorityYaml);
|
string p = ExpandEnv(this.PriorityYaml);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -604,7 +602,7 @@ namespace WinSW.Configuration
|
||||||
|
|
||||||
var result = new List<string>(0);
|
var result = new List<string>(0);
|
||||||
|
|
||||||
foreach (var item in this.ServiceDependenciesYaml)
|
foreach (string item in this.ServiceDependenciesYaml)
|
||||||
{
|
{
|
||||||
result.Add(ExpandEnv(item));
|
result.Add(ExpandEnv(item));
|
||||||
}
|
}
|
||||||
|
@ -638,8 +636,8 @@ namespace WinSW.Configuration
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = item.Name;
|
string key = item.Name;
|
||||||
var value = ExpandEnv(item.Value);
|
string value = ExpandEnv(item.Value);
|
||||||
|
|
||||||
this.EnvironmentVariables[key] = value;
|
this.EnvironmentVariables[key] = value;
|
||||||
Environment.SetEnvironmentVariable(key, value);
|
Environment.SetEnvironmentVariable(key, value);
|
||||||
|
|
|
@ -150,10 +150,10 @@ namespace WinSW
|
||||||
public void Perform()
|
public void Perform()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
@ -196,12 +196,12 @@ namespace WinSW
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
using (WebResponse response = await request.GetResponseAsync())
|
using (var response = await request.GetResponseAsync())
|
||||||
#else
|
#else
|
||||||
using (WebResponse response = request.GetResponse())
|
using (var response = request.GetResponse())
|
||||||
#endif
|
#endif
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace DynamicProxy
|
||||||
private const string ModuleName = "ProxyModule";
|
private const string ModuleName = "ProxyModule";
|
||||||
private const string HandlerName = "handler";
|
private const string HandlerName = "handler";
|
||||||
|
|
||||||
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
|
private static readonly Dictionary<string, Type> TypeCache = new();
|
||||||
|
|
||||||
private static readonly AssemblyBuilder AssemblyBuilder =
|
private static readonly AssemblyBuilder AssemblyBuilder =
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
|
@ -57,26 +57,26 @@ namespace DynamicProxy
|
||||||
|
|
||||||
private static Type CreateType(string dynamicTypeName, Type[] interfaces)
|
private static Type CreateType(string dynamicTypeName, Type[] interfaces)
|
||||||
{
|
{
|
||||||
Type objType = typeof(object);
|
var objType = typeof(object);
|
||||||
Type handlerType = typeof(IProxyInvocationHandler);
|
var handlerType = typeof(IProxyInvocationHandler);
|
||||||
|
|
||||||
TypeAttributes typeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
|
var typeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
|
||||||
|
|
||||||
// Gather up the proxy information and create a new type builder. One that
|
// Gather up the proxy information and create a new type builder. One that
|
||||||
// inherits from Object and implements the interface passed in
|
// inherits from Object and implements the interface passed in
|
||||||
TypeBuilder typeBuilder = ModuleBuilder.DefineType(
|
var typeBuilder = ModuleBuilder.DefineType(
|
||||||
dynamicTypeName, typeAttributes, objType, interfaces);
|
dynamicTypeName, typeAttributes, objType, interfaces);
|
||||||
|
|
||||||
// Define a member variable to hold the delegate
|
// Define a member variable to hold the delegate
|
||||||
FieldBuilder handlerField = typeBuilder.DefineField(
|
var handlerField = typeBuilder.DefineField(
|
||||||
HandlerName, handlerType, FieldAttributes.Private | FieldAttributes.InitOnly);
|
HandlerName, handlerType, FieldAttributes.Private | FieldAttributes.InitOnly);
|
||||||
|
|
||||||
// build a constructor that takes the delegate object as the only argument
|
// build a constructor that takes the delegate object as the only argument
|
||||||
ConstructorInfo baseConstructor = objType.GetConstructor(Type.EmptyTypes)!;
|
var baseConstructor = objType.GetConstructor(Type.EmptyTypes)!;
|
||||||
ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
|
var delegateConstructor = typeBuilder.DefineConstructor(
|
||||||
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
|
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
|
||||||
|
|
||||||
ILGenerator constructorIL = delegateConstructor.GetILGenerator();
|
var constructorIL = delegateConstructor.GetILGenerator();
|
||||||
|
|
||||||
// Load "this"
|
// Load "this"
|
||||||
constructorIL.Emit(OpCodes.Ldarg_0);
|
constructorIL.Emit(OpCodes.Ldarg_0);
|
||||||
|
@ -98,7 +98,7 @@ namespace DynamicProxy
|
||||||
|
|
||||||
// for every method that the interfaces define, build a corresponding
|
// for every method that the interfaces define, build a corresponding
|
||||||
// method in the dynamic type that calls the handlers invoke method.
|
// method in the dynamic type that calls the handlers invoke method.
|
||||||
foreach (Type interfaceType in interfaces)
|
foreach (var interfaceType in interfaces)
|
||||||
{
|
{
|
||||||
GenerateMethod(interfaceType, handlerField, typeBuilder);
|
GenerateMethod(interfaceType, handlerField, typeBuilder);
|
||||||
}
|
}
|
||||||
|
@ -118,17 +118,17 @@ namespace DynamicProxy
|
||||||
|
|
||||||
private static void GenerateMethod(Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder)
|
private static void GenerateMethod(Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder)
|
||||||
{
|
{
|
||||||
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
|
var interfaceMethods = interfaceType.GetMethods();
|
||||||
|
|
||||||
for (int i = 0; i < interfaceMethods.Length; i++)
|
for (int i = 0; i < interfaceMethods.Length; i++)
|
||||||
{
|
{
|
||||||
MethodInfo methodInfo = interfaceMethods[i];
|
var methodInfo = interfaceMethods[i];
|
||||||
|
|
||||||
// Get the method parameters since we need to create an array
|
// Get the method parameters since we need to create an array
|
||||||
// of parameter types
|
// of parameter types
|
||||||
ParameterInfo[] methodParams = methodInfo.GetParameters();
|
var methodParams = methodInfo.GetParameters();
|
||||||
int numOfParams = methodParams.Length;
|
int numOfParams = methodParams.Length;
|
||||||
Type[] methodParameters = new Type[numOfParams];
|
var methodParameters = new Type[numOfParams];
|
||||||
|
|
||||||
// convert the ParameterInfo objects into Type
|
// convert the ParameterInfo objects into Type
|
||||||
for (int j = 0; j < numOfParams; j++)
|
for (int j = 0; j < numOfParams; j++)
|
||||||
|
@ -137,14 +137,14 @@ namespace DynamicProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new builder for the method in the interface
|
// create a new builder for the method in the interface
|
||||||
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
|
var methodBuilder = typeBuilder.DefineMethod(
|
||||||
methodInfo.Name,
|
methodInfo.Name,
|
||||||
/*MethodAttributes.Public | MethodAttributes.Virtual | */ methodInfo.Attributes & ~MethodAttributes.Abstract,
|
/*MethodAttributes.Public | MethodAttributes.Virtual | */ methodInfo.Attributes & ~MethodAttributes.Abstract,
|
||||||
CallingConventions.Standard,
|
CallingConventions.Standard,
|
||||||
methodInfo.ReturnType,
|
methodInfo.ReturnType,
|
||||||
methodParameters);
|
methodParameters);
|
||||||
|
|
||||||
ILGenerator methodIL = methodBuilder.GetILGenerator();
|
var methodIL = methodBuilder.GetILGenerator();
|
||||||
|
|
||||||
// invoke target: IProxyInvocationHandler
|
// invoke target: IProxyInvocationHandler
|
||||||
methodIL.Emit(OpCodes.Ldarg_0);
|
methodIL.Emit(OpCodes.Ldarg_0);
|
||||||
|
@ -196,7 +196,7 @@ namespace DynamicProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through the parent interfaces and recursively call this method
|
// Iterate through the parent interfaces and recursively call this method
|
||||||
foreach (Type parentType in interfaceType.GetInterfaces())
|
foreach (var parentType in interfaceType.GetInterfaces())
|
||||||
{
|
{
|
||||||
GenerateMethod(parentType, handlerField, typeBuilder);
|
GenerateMethod(parentType, handlerField, typeBuilder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,8 +140,8 @@ namespace WinSW.Extensions
|
||||||
|
|
||||||
private void LoadExtensionFromXml(string id)
|
private void LoadExtensionFromXml(string id)
|
||||||
{
|
{
|
||||||
XmlNode? extensionsConfig = this.ServiceDescriptor.ExtensionsConfiguration;
|
var extensionsConfig = this.ServiceDescriptor.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");
|
||||||
|
@ -151,7 +151,7 @@ namespace WinSW.Extensions
|
||||||
|
|
||||||
if (descriptor.Enabled)
|
if (descriptor.Enabled)
|
||||||
{
|
{
|
||||||
IWinSWExtension extension = this.CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
|
var extension = this.CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
|
||||||
extension.Descriptor = descriptor;
|
extension.Descriptor = descriptor;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -187,7 +187,7 @@ namespace WinSW.Extensions
|
||||||
|
|
||||||
if (descriptor.Enabled)
|
if (descriptor.Enabled)
|
||||||
{
|
{
|
||||||
IWinSWExtension extension = this.CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
|
var extension = this.CreateExtensionInstance(descriptor.Id, descriptor.ClassName);
|
||||||
extension.Descriptor = descriptor;
|
extension.Descriptor = descriptor;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -237,7 +237,7 @@ namespace WinSW.Extensions
|
||||||
className = "WinSW.Plugins.SharedDirectoryMapper";
|
className = "WinSW.Plugins.SharedDirectoryMapper";
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
|
|
|
@ -107,7 +107,7 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected StreamWriter CreateWriter(FileStream stream) => new StreamWriter(stream) { AutoFlush = true };
|
protected StreamWriter CreateWriter(FileStream stream) => new(stream) { AutoFlush = true };
|
||||||
|
|
||||||
protected abstract void LogOutput(StreamReader outputReader);
|
protected abstract void LogOutput(StreamReader outputReader);
|
||||||
|
|
||||||
|
@ -200,10 +200,10 @@ namespace WinSW
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void CopyStreamWithDateRotation(StreamReader reader, string ext)
|
private void CopyStreamWithDateRotation(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 = reader.ReadLine()) != null)
|
while ((line = reader.ReadLine()) != null)
|
||||||
{
|
{
|
||||||
|
@ -259,7 +259,7 @@ namespace WinSW
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void CopyStreamWithRotation(StreamReader reader, string ext)
|
private void CopyStreamWithRotation(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;
|
||||||
|
@ -383,20 +383,20 @@ namespace WinSW
|
||||||
private void CopyStreamWithRotation(StreamReader reader, string extension)
|
private void CopyStreamWithRotation(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 += (s, e) =>
|
timer.Elapsed += (s, e) =>
|
||||||
{
|
{
|
||||||
|
@ -408,8 +408,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));
|
||||||
|
@ -445,8 +445,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);
|
||||||
|
@ -574,21 +574,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)
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace WinSW.Logging
|
||||||
|
|
||||||
protected override void Append(LoggingEvent loggingEvent)
|
protected override void Append(LoggingEvent loggingEvent)
|
||||||
{
|
{
|
||||||
EventLog? 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));
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace WinSW.Native
|
||||||
{
|
{
|
||||||
internal static void AddServiceLogonRight(string domain, string user)
|
internal static void AddServiceLogonRight(string domain, string user)
|
||||||
{
|
{
|
||||||
IntPtr sid = GetAccountSid(domain, user);
|
var sid = GetAccountSid(domain, user);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -34,8 +34,8 @@ namespace WinSW.Native
|
||||||
string accountName = domain + "\\" + user;
|
string accountName = domain + "\\" + user;
|
||||||
_ = LookupAccountName(null, accountName, IntPtr.Zero, ref sidSize, IntPtr.Zero, ref domainNameLength, out _);
|
_ = LookupAccountName(null, accountName, IntPtr.Zero, ref sidSize, IntPtr.Zero, ref domainNameLength, out _);
|
||||||
|
|
||||||
IntPtr sid = Marshal.AllocHGlobal(sidSize);
|
var sid = Marshal.AllocHGlobal(sidSize);
|
||||||
IntPtr domainName = Marshal.AllocHGlobal(domainNameLength * sizeof(char));
|
var domainName = Marshal.AllocHGlobal(domainNameLength * sizeof(char));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,7 @@ namespace WinSW.Native
|
||||||
|
|
||||||
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));
|
||||||
|
@ -62,7 +62,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)),
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace WinSW.Native
|
||||||
|
|
||||||
internal static ServiceManager Open()
|
internal static ServiceManager Open()
|
||||||
{
|
{
|
||||||
IntPtr handle = OpenSCManager(null, null, ServiceManagerAccess.ALL_ACCESS);
|
var handle = OpenSCManager(null, null, ServiceManagerAccess.ALL_ACCESS);
|
||||||
if (handle == IntPtr.Zero)
|
if (handle == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Throw.Win32Exception("Failed to open the service control manager database.");
|
Throw.Win32Exception("Failed to open the service control manager database.");
|
||||||
|
@ -65,7 +65,7 @@ namespace WinSW.Native
|
||||||
|
|
||||||
internal Service OpenService(string serviceName)
|
internal Service OpenService(string serviceName)
|
||||||
{
|
{
|
||||||
IntPtr serviceHandle = ServiceApis.OpenService(this.handle, serviceName, ServiceAccess.ALL_ACCESS);
|
var serviceHandle = ServiceApis.OpenService(this.handle, serviceName, ServiceAccess.ALL_ACCESS);
|
||||||
if (serviceHandle == IntPtr.Zero)
|
if (serviceHandle == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Throw.Win32Exception("Failed to open the service.");
|
Throw.Win32Exception("Failed to open the service.");
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace WinSW.Native
|
||||||
{
|
{
|
||||||
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 Win32Exception(inner.NativeErrorCode, message + ' ' + inner.Message);
|
throw new Win32Exception(inner.NativeErrorCode, message + ' ' + inner.Message);
|
||||||
|
|
|
@ -40,15 +40,15 @@ namespace WinSW
|
||||||
|
|
||||||
private Periodicity DeterminePeriodicityType()
|
private Periodicity 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 (Periodicity i in ValidOrderedList)
|
foreach (var i in ValidOrderedList)
|
||||||
{
|
{
|
||||||
string r0 = epoch.ToString(this.format);
|
string r0 = epoch.ToString(this.format);
|
||||||
periodicRollingCalendar.PeriodicityType = i;
|
periodicRollingCalendar.PeriodicityType = 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;
|
||||||
|
|
|
@ -16,10 +16,7 @@ namespace WinSW
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ServiceDescriptor : IWinSWConfiguration
|
public class ServiceDescriptor : IWinSWConfiguration
|
||||||
{
|
{
|
||||||
#pragma warning disable S2755 // XML parsers should not be vulnerable to XXE attacks
|
protected readonly XmlDocument dom = new();
|
||||||
protected readonly XmlDocument dom = new XmlDocument();
|
|
||||||
#pragma warning restore S2755 // XML parsers should not be vulnerable to XXE attacks
|
|
||||||
|
|
||||||
private readonly Dictionary<string, string> environmentVariables;
|
private readonly Dictionary<string, string> environmentVariables;
|
||||||
|
|
||||||
public static DefaultWinSWSettings Defaults { get; } = new DefaultWinSWSettings();
|
public static DefaultWinSWSettings Defaults { get; } = new DefaultWinSWSettings();
|
||||||
|
@ -84,9 +81,7 @@ namespace WinSW
|
||||||
|
|
||||||
public static ServiceDescriptor FromXML(string xml)
|
public static ServiceDescriptor FromXML(string xml)
|
||||||
{
|
{
|
||||||
#pragma warning disable S2755 // XML parsers should not be vulnerable to XXE attacks
|
|
||||||
var xmlDom = new XmlDocument();
|
var xmlDom = new XmlDocument();
|
||||||
#pragma warning restore S2755 // XML parsers should not be vulnerable to XXE attacks
|
|
||||||
xmlDom.LoadXml(xml);
|
xmlDom.LoadXml(xml);
|
||||||
return new ServiceDescriptor(xmlDom);
|
return new ServiceDescriptor(xmlDom);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +93,7 @@ namespace WinSW
|
||||||
|
|
||||||
private string? SingleElement(string tagName, bool optional)
|
private string? SingleElement(string tagName, bool optional)
|
||||||
{
|
{
|
||||||
XmlNode? n = this.dom.SelectSingleNode("//" + tagName);
|
var n = this.dom.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");
|
||||||
|
@ -109,14 +104,14 @@ namespace WinSW
|
||||||
|
|
||||||
private bool SingleBoolElement(string tagName, bool defaultValue)
|
private bool SingleBoolElement(string tagName, bool defaultValue)
|
||||||
{
|
{
|
||||||
XmlNode? e = this.dom.SelectSingleNode("//" + tagName);
|
var e = this.dom.SelectSingleNode("//" + tagName);
|
||||||
|
|
||||||
return e is null ? defaultValue : bool.Parse(e.InnerText);
|
return e is null ? defaultValue : bool.Parse(e.InnerText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int SingleIntElement(XmlNode parent, string tagName, int defaultValue)
|
private 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);
|
return e is null ? defaultValue : int.Parse(e.InnerText);
|
||||||
}
|
}
|
||||||
|
@ -153,7 +148,7 @@ namespace WinSW
|
||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlNode? argumentsNode = this.dom.SelectSingleNode("//arguments");
|
var argumentsNode = this.dom.SelectSingleNode("//arguments");
|
||||||
|
|
||||||
return argumentsNode is null ? Defaults.Arguments : Environment.ExpandEnvironmentVariables(argumentsNode.InnerText);
|
return argumentsNode is null ? Defaults.Arguments : Environment.ExpandEnvironmentVariables(argumentsNode.InnerText);
|
||||||
}
|
}
|
||||||
|
@ -173,7 +168,7 @@ namespace WinSW
|
||||||
return startArguments;
|
return startArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlNode? startArgumentsNode = this.dom.SelectSingleNode("//startarguments");
|
var startArgumentsNode = this.dom.SelectSingleNode("//startarguments");
|
||||||
|
|
||||||
return startArgumentsNode is null ? null : Environment.ExpandEnvironmentVariables(startArgumentsNode.InnerText);
|
return startArgumentsNode is null ? null : Environment.ExpandEnvironmentVariables(startArgumentsNode.InnerText);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +188,7 @@ namespace WinSW
|
||||||
return stopArguments;
|
return stopArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlNode? stopArgumentsNode = this.dom.SelectSingleNode("//stoparguments");
|
var stopArgumentsNode = this.dom.SelectSingleNode("//stoparguments");
|
||||||
|
|
||||||
return stopArgumentsNode is null ? null : Environment.ExpandEnvironmentVariables(stopArgumentsNode.InnerText);
|
return stopArgumentsNode is null ? null : Environment.ExpandEnvironmentVariables(stopArgumentsNode.InnerText);
|
||||||
}
|
}
|
||||||
|
@ -203,7 +198,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var wd = this.SingleElement("workingdirectory", true);
|
string? wd = this.SingleElement("workingdirectory", true);
|
||||||
return string.IsNullOrEmpty(wd) ? Defaults.WorkingDirectory : wd!;
|
return string.IsNullOrEmpty(wd) ? Defaults.WorkingDirectory : wd!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,14 +207,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"));
|
||||||
|
@ -237,15 +232,15 @@ namespace WinSW
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string? AppendTags(string tagName, string? defaultValue = null)
|
private string? AppendTags(string tagName, string? defaultValue = null)
|
||||||
{
|
{
|
||||||
XmlNode? argumentNode = this.dom.SelectSingleNode("//" + tagName);
|
var argumentNode = this.dom.SelectSingleNode("//" + tagName);
|
||||||
if (argumentNode is null)
|
if (argumentNode is null)
|
||||||
{
|
{
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder arguments = new StringBuilder();
|
var arguments = new StringBuilder();
|
||||||
|
|
||||||
XmlNodeList argumentNodeList = this.dom.SelectNodes("//" + tagName)!;
|
var argumentNodeList = this.dom.SelectNodes("//" + tagName)!;
|
||||||
for (int i = 0; i < argumentNodeList.Count; i++)
|
for (int i = 0; i < argumentNodeList.Count; i++)
|
||||||
{
|
{
|
||||||
arguments.Append(' ');
|
arguments.Append(' ');
|
||||||
|
@ -276,7 +271,7 @@ namespace WinSW
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LogDirectory is the service wrapper executable directory or the optionally specified logpath element.
|
/// LogDirectory is the service wrapper executable directory or the optionally specified logpath element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LogDirectory { get => this.Log.Directory; }
|
public string LogDirectory => this.Log.Directory;
|
||||||
|
|
||||||
public string LogMode
|
public string LogMode
|
||||||
{
|
{
|
||||||
|
@ -285,7 +280,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.dom.SelectSingleNode("//logmode");
|
var e = (XmlElement?)this.dom.SelectSingleNode("//logmode");
|
||||||
if (e != null)
|
if (e != null)
|
||||||
{
|
{
|
||||||
mode = e.InnerText;
|
mode = e.InnerText;
|
||||||
|
@ -308,19 +303,13 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? loggingName = this.dom.SelectSingleNode("//logname");
|
var loggingName = this.dom.SelectSingleNode("//logname");
|
||||||
|
|
||||||
return loggingName is null ? this.BaseName : Environment.ExpandEnvironmentVariables(loggingName.InnerText);
|
return loggingName is null ? this.BaseName : Environment.ExpandEnvironmentVariables(loggingName.InnerText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Log Log
|
public Log Log => new XmlLogSettings(this);
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new XmlLogSettings(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class XmlLogSettings : Log
|
private class XmlLogSettings : Log
|
||||||
{
|
{
|
||||||
|
@ -335,7 +324,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlElement? e = (XmlElement?)this.d.dom.SelectSingleNode("//logmode");
|
var e = (XmlElement?)this.d.dom.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.d.dom.SelectSingleNode("//log")!; // WARNING: NRE
|
e ??= (XmlElement?)this.d.dom.SelectSingleNode("//log")!; // WARNING: NRE
|
||||||
|
@ -343,15 +332,15 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string? Mode { get => this.d.LogMode; }
|
public override string? Mode => this.d.LogMode;
|
||||||
|
|
||||||
public override string Name { get => this.d.LogName; }
|
public override string Name => this.d.LogName;
|
||||||
|
|
||||||
public override string Directory
|
public override string Directory
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? loggingNode = this.d.dom.SelectSingleNode("//logpath");
|
var loggingNode = this.d.dom.SelectSingleNode("//logpath");
|
||||||
|
|
||||||
return loggingNode is null
|
return loggingNode is null
|
||||||
? Defaults.LogDirectory
|
? Defaults.LogDirectory
|
||||||
|
@ -359,22 +348,20 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int? SizeThreshold { get => this.d.SingleIntElement(this.E, "sizeThreshold", 10 * 1024); }
|
public override int? SizeThreshold => this.d.SingleIntElement(this.E, "sizeThreshold", 10 * 1024);
|
||||||
|
|
||||||
public override int? KeepFiles { get => this.d.SingleIntElement(this.E, "keepFiles", SizeBasedRollingLogAppender.DefaultFilesToKeep); }
|
public override int? KeepFiles => this.d.SingleIntElement(this.E, "keepFiles", SizeBasedRollingLogAppender.DefaultFilesToKeep);
|
||||||
|
|
||||||
public override int? Period { get => this.d.SingleIntElement(this.E, "period", 1); }
|
public override int? Period => this.d.SingleIntElement(this.E, "period", 1);
|
||||||
|
|
||||||
public override string Pattern
|
public override string Pattern
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? patternNode = this.E.SelectSingleNode("pattern");
|
var patternNode = this.E.SelectSingleNode("pattern");
|
||||||
if (patternNode is null)
|
if (patternNode is null)
|
||||||
{
|
{
|
||||||
#pragma warning disable S2372 // Exceptions should not be thrown from property getters
|
|
||||||
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.");
|
||||||
#pragma warning restore S2372 // Exceptions should not be thrown from property getters
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return patternNode.InnerText;
|
return patternNode.InnerText;
|
||||||
|
@ -389,7 +376,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? loggingName = this.d.dom.SelectSingleNode("//outfilepattern");
|
var loggingName = this.d.dom.SelectSingleNode("//outfilepattern");
|
||||||
|
|
||||||
return loggingName is null ? Defaults.OutFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText);
|
return loggingName is null ? Defaults.OutFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText);
|
||||||
}
|
}
|
||||||
|
@ -399,7 +386,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? loggingName = this.d.dom.SelectSingleNode("//errfilepattern");
|
var loggingName = this.d.dom.SelectSingleNode("//errfilepattern");
|
||||||
|
|
||||||
return loggingName is null ? Defaults.ErrFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText);
|
return loggingName is null ? Defaults.ErrFilePattern : Environment.ExpandEnvironmentVariables(loggingName.InnerText);
|
||||||
}
|
}
|
||||||
|
@ -409,7 +396,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? autoRollAtTimeNode = this.E.SelectSingleNode("autoRollAtTime");
|
var autoRollAtTimeNode = this.E.SelectSingleNode("autoRollAtTime");
|
||||||
return autoRollAtTimeNode?.InnerText;
|
return autoRollAtTimeNode?.InnerText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,16 +405,14 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? zipolderthannumdaysNode = this.E.SelectSingleNode("zipOlderThanNumDays");
|
var zipolderthannumdaysNode = this.E.SelectSingleNode("zipOlderThanNumDays");
|
||||||
int? zipolderthannumdays = null;
|
int? zipolderthannumdays = null;
|
||||||
if (zipolderthannumdaysNode != null)
|
if (zipolderthannumdaysNode != null)
|
||||||
{
|
{
|
||||||
// validate it
|
// validate it
|
||||||
if (!int.TryParse(zipolderthannumdaysNode.InnerText, out int zipolderthannumdaysValue))
|
if (!int.TryParse(zipolderthannumdaysNode.InnerText, out int zipolderthannumdaysValue))
|
||||||
{
|
{
|
||||||
#pragma warning disable S2372 // Exceptions should not be thrown from property getters
|
|
||||||
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but zipOlderThanNumDays does not match the int format found in configuration XML.");
|
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but zipOlderThanNumDays does not match the int format found in configuration XML.");
|
||||||
#pragma warning restore S2372 // Exceptions should not be thrown from property getters
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zipolderthannumdays = zipolderthannumdaysValue;
|
zipolderthannumdays = zipolderthannumdaysValue;
|
||||||
|
@ -441,7 +426,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? zipdateformatNode = this.E.SelectSingleNode("zipDateFormat");
|
var zipdateformatNode = this.E.SelectSingleNode("zipDateFormat");
|
||||||
return zipdateformatNode is null ? null : zipdateformatNode.InnerText;
|
return zipdateformatNode is null ? null : zipdateformatNode.InnerText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,7 +439,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNodeList? nodeList = this.dom.SelectNodes("//depend");
|
var nodeList = this.dom.SelectNodes("//depend");
|
||||||
if (nodeList is null)
|
if (nodeList is null)
|
||||||
{
|
{
|
||||||
return Defaults.ServiceDependencies;
|
return Defaults.ServiceDependencies;
|
||||||
|
@ -540,7 +525,7 @@ namespace WinSW
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Environment variable overrides
|
/// Environment variable overrides
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<string, string> EnvironmentVariables => new Dictionary<string, string>(this.environmentVariables);
|
public Dictionary<string, string> EnvironmentVariables => new(this.environmentVariables);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of downloads to be performed by the wrapper before starting
|
/// List of downloads to be performed by the wrapper before starting
|
||||||
|
@ -550,13 +535,13 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNodeList? nodeList = this.dom.SelectNodes("//download");
|
var nodeList = this.dom.SelectNodes("//download");
|
||||||
if (nodeList is null)
|
if (nodeList is null)
|
||||||
{
|
{
|
||||||
return Defaults.Downloads;
|
return Defaults.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)
|
||||||
|
@ -573,25 +558,25 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNodeList? childNodes = this.dom.SelectNodes("//onfailure");
|
var childNodes = this.dom.SelectNodes("//onfailure");
|
||||||
if (childNodes is null)
|
if (childNodes is null)
|
||||||
{
|
{
|
||||||
return new SC_ACTION[0];
|
return new SC_ACTION[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
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 ? ConfigHelper.ParseTimeSpan(delay.Value) : TimeSpan.Zero);
|
result[i] = new SC_ACTION(type, delay != null ? ConfigHelper.ParseTimeSpan(delay.Value) : TimeSpan.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,7 +588,7 @@ namespace WinSW
|
||||||
|
|
||||||
protected string? GetServiceAccountPart(XmlNode node, string subNodeName)
|
protected string? GetServiceAccountPart(XmlNode node, string subNodeName)
|
||||||
{
|
{
|
||||||
XmlNode? subNode = node.SelectSingleNode(subNodeName);
|
var subNode = node.SelectSingleNode(subNodeName);
|
||||||
if (subNode != null)
|
if (subNode != null)
|
||||||
{
|
{
|
||||||
return subNode.InnerText;
|
return subNode.InnerText;
|
||||||
|
@ -626,7 +611,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
XmlNode? node = this.dom.SelectSingleNode("//serviceaccount");
|
var node = this.dom.SelectSingleNode("//serviceaccount");
|
||||||
|
|
||||||
if (node is null)
|
if (node is null)
|
||||||
{
|
{
|
||||||
|
@ -641,7 +626,7 @@ namespace WinSW
|
||||||
|
|
||||||
serviceAccount.ServiceAccountPassword = this.GetServiceAccountPart(node, "password");
|
serviceAccount.ServiceAccountPassword = this.GetServiceAccountPart(node, "password");
|
||||||
|
|
||||||
var loginRight = this.GetServiceAccountPart(node, "allowservicelogon");
|
string? loginRight = this.GetServiceAccountPart(node, "allowservicelogon");
|
||||||
|
|
||||||
serviceAccount.AllowServiceAcountLogonRight = this.ParseAllowServiceAcountLogonRight(loginRight);
|
serviceAccount.AllowServiceAcountLogonRight = this.ParseAllowServiceAcountLogonRight(loginRight);
|
||||||
|
|
||||||
|
@ -658,7 +643,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var value = this.SingleElement("stopparentprocessfirst", true);
|
string? value = this.SingleElement("stopparentprocessfirst", true);
|
||||||
if (bool.TryParse(value, out bool result))
|
if (bool.TryParse(value, out bool result))
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
|
@ -689,11 +674,11 @@ namespace WinSW
|
||||||
|
|
||||||
private Dictionary<string, string> LoadEnvironmentVariables()
|
private Dictionary<string, string> LoadEnvironmentVariables()
|
||||||
{
|
{
|
||||||
XmlNodeList nodeList = this.dom.SelectNodes("//env")!;
|
var nodeList = this.dom.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;
|
||||||
|
|
|
@ -13,11 +13,11 @@ namespace WinSW
|
||||||
|
|
||||||
public ServiceDescriptorYaml(string baseName, DirectoryInfo d)
|
public ServiceDescriptorYaml(string baseName, DirectoryInfo d)
|
||||||
{
|
{
|
||||||
var basepath = Path.Combine(d.FullName, baseName);
|
string basepath = Path.Combine(d.FullName, baseName);
|
||||||
|
|
||||||
using (var reader = new StreamReader(basepath + ".yml"))
|
using (var reader = new StreamReader(basepath + ".yml"))
|
||||||
{
|
{
|
||||||
var file = reader.ReadToEnd();
|
string file = reader.ReadToEnd();
|
||||||
var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build();
|
var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build();
|
||||||
|
|
||||||
this.Configurations = deserializer.Deserialize<YamlConfiguration>(file);
|
this.Configurations = deserializer.Deserialize<YamlConfiguration>(file);
|
||||||
|
@ -37,9 +37,7 @@ namespace WinSW
|
||||||
this.Configurations.LoadEnvironmentVariables();
|
this.Configurations.LoadEnvironmentVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable.
|
|
||||||
public ServiceDescriptorYaml(YamlConfiguration configs)
|
public ServiceDescriptorYaml(YamlConfiguration configs)
|
||||||
#pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable.
|
|
||||||
{
|
{
|
||||||
this.Configurations = configs;
|
this.Configurations = configs;
|
||||||
this.Configurations.LoadEnvironmentVariables();
|
this.Configurations.LoadEnvironmentVariables();
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace WinSW.Util
|
||||||
return TimeSpan.FromMilliseconds(int.Parse(v));
|
return TimeSpan.FromMilliseconds(int.Parse(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<string, long> Suffix = new Dictionary<string, long>
|
private static readonly Dictionary<string, long> Suffix = new()
|
||||||
{
|
{
|
||||||
{ "ms", 1 },
|
{ "ms", 1 },
|
||||||
{ "sec", 1000L },
|
{ "sec", 1000L },
|
||||||
|
|
|
@ -29,11 +29,11 @@ namespace WinSW.Util
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string query = "SELECT * FROM Win32_Process WHERE ParentProcessID = " + pid;
|
string query = "SELECT * FROM Win32_Process WHERE ParentProcessID = " + pid;
|
||||||
using ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
|
using var searcher = new ManagementObjectSearcher(query);
|
||||||
using ManagementObjectCollection results = searcher.Get();
|
using var results = searcher.Get();
|
||||||
foreach (ManagementBaseObject wmiObject in results)
|
foreach (var wmiObject in results)
|
||||||
{
|
{
|
||||||
var childProcessId = wmiObject["ProcessID"];
|
object childProcessId = wmiObject["ProcessID"];
|
||||||
Logger.Info("Found child process: " + childProcessId + " Name: " + wmiObject["Name"]);
|
Logger.Info("Found child process: " + childProcessId + " Name: " + wmiObject["Name"]);
|
||||||
childPids.Add(Convert.ToInt32(childProcessId));
|
childPids.Add(Convert.ToInt32(childProcessId));
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ namespace WinSW.Util
|
||||||
}
|
}
|
||||||
|
|
||||||
// (bool sent, bool exited)
|
// (bool sent, bool exited)
|
||||||
KeyValuePair<bool, bool> result = SignalHelper.SendCtrlCToProcess(proc, stopTimeout);
|
var result = SignalHelper.SendCtrlCToProcess(proc, stopTimeout);
|
||||||
bool exited = result.Value;
|
bool exited = result.Value;
|
||||||
if (!exited)
|
if (!exited)
|
||||||
{
|
{
|
||||||
|
@ -107,7 +107,7 @@ namespace WinSW.Util
|
||||||
{
|
{
|
||||||
if (!stopParentProcessFirst)
|
if (!stopParentProcessFirst)
|
||||||
{
|
{
|
||||||
foreach (var childPid in GetChildPids(pid))
|
foreach (int childPid in GetChildPids(pid))
|
||||||
{
|
{
|
||||||
StopProcessAndChildren(childPid, stopTimeout, stopParentProcessFirst);
|
StopProcessAndChildren(childPid, stopTimeout, stopParentProcessFirst);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ namespace WinSW.Util
|
||||||
|
|
||||||
if (stopParentProcessFirst)
|
if (stopParentProcessFirst)
|
||||||
{
|
{
|
||||||
foreach (var childPid in GetChildPids(pid))
|
foreach (int childPid in GetChildPids(pid))
|
||||||
{
|
{
|
||||||
StopProcessAndChildren(childPid, stopTimeout, stopParentProcessFirst);
|
StopProcessAndChildren(childPid, stopTimeout, stopParentProcessFirst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
|
@ -105,7 +105,7 @@ namespace WinSW.Util
|
||||||
#if NET20
|
#if NET20
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var value = Enum.Parse(typeof(TAttributeType), substitutedValue, true);
|
object value = Enum.Parse(typeof(TAttributeType), substitutedValue, true);
|
||||||
return (TAttributeType)value;
|
return (TAttributeType)value;
|
||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace WMI
|
||||||
|
|
||||||
public WmiRoot()
|
public WmiRoot()
|
||||||
{
|
{
|
||||||
ConnectionOptions options = new ConnectionOptions
|
var options = new ConnectionOptions
|
||||||
{
|
{
|
||||||
EnablePrivileges = true,
|
EnablePrivileges = true,
|
||||||
Impersonation = ImpersonationLevel.Impersonate,
|
Impersonation = ImpersonationLevel.Impersonate,
|
||||||
|
@ -118,7 +118,7 @@ namespace WMI
|
||||||
|
|
||||||
protected ManagementBaseObject GetMethodParameters(ManagementObject wmiObject, string methodName, ParameterInfo[] methodParameters, object[] arguments)
|
protected ManagementBaseObject GetMethodParameters(ManagementObject wmiObject, string methodName, ParameterInfo[] methodParameters, object[] arguments)
|
||||||
{
|
{
|
||||||
ManagementBaseObject wmiParameters = wmiObject.GetMethodParameters(methodName);
|
var wmiParameters = wmiObject.GetMethodParameters(methodName);
|
||||||
for (int i = 0; i < arguments.Length; i++)
|
for (int i = 0; i < arguments.Length; i++)
|
||||||
{
|
{
|
||||||
string capitalizedName = Capitalize(methodParameters[i].Name!);
|
string capitalizedName = Capitalize(methodParameters[i].Name!);
|
||||||
|
@ -155,9 +155,9 @@ namespace WMI
|
||||||
}
|
}
|
||||||
|
|
||||||
string methodName = method.Name;
|
string methodName = method.Name;
|
||||||
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
|
using var wmiParameters = arguments.Length == 0 ? null :
|
||||||
this.GetMethodParameters(this.wmiObject, methodName, method.GetParameters(), arguments);
|
this.GetMethodParameters(this.wmiObject, methodName, method.GetParameters(), arguments);
|
||||||
using ManagementBaseObject result = this.wmiObject.InvokeMethod(methodName, wmiParameters, null);
|
using var result = this.wmiObject.InvokeMethod(methodName, wmiParameters, null);
|
||||||
this.CheckError(result);
|
this.CheckError(result);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -176,12 +176,12 @@ namespace WMI
|
||||||
|
|
||||||
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
|
public override object? Invoke(object proxy, MethodInfo method, object[] arguments)
|
||||||
{
|
{
|
||||||
ParameterInfo[] methodParameters = method.GetParameters();
|
var methodParameters = method.GetParameters();
|
||||||
|
|
||||||
if (method.Name == nameof(IWin32Services.Select))
|
if (method.Name == nameof(IWin32Services.Select))
|
||||||
{
|
{
|
||||||
// select method to find instances
|
// select method to find instances
|
||||||
StringBuilder query = new StringBuilder("SELECT * FROM ").Append(this.className).Append(" WHERE ");
|
var query = new StringBuilder("SELECT * FROM ").Append(this.className).Append(" WHERE ");
|
||||||
for (int i = 0; i < arguments.Length; i++)
|
for (int i = 0; i < arguments.Length; i++)
|
||||||
{
|
{
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
|
@ -192,8 +192,8 @@ namespace WMI
|
||||||
query.Append(' ').Append(Capitalize(methodParameters[i].Name!)).Append(" = '").Append(arguments[i]).Append('\'');
|
query.Append(' ').Append(Capitalize(methodParameters[i].Name!)).Append(" = '").Append(arguments[i]).Append('\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
using ManagementObjectSearcher searcher = new ManagementObjectSearcher(this.wmiClass.Scope, new ObjectQuery(query.ToString()));
|
using var searcher = new ManagementObjectSearcher(this.wmiClass.Scope, new ObjectQuery(query.ToString()));
|
||||||
using ManagementObjectCollection results = searcher.Get();
|
using var results = searcher.Get();
|
||||||
|
|
||||||
// TODO: support collections
|
// TODO: support collections
|
||||||
foreach (ManagementObject wmiObject in results)
|
foreach (ManagementObject wmiObject in results)
|
||||||
|
@ -205,9 +205,9 @@ namespace WMI
|
||||||
}
|
}
|
||||||
|
|
||||||
string methodName = method.Name;
|
string methodName = method.Name;
|
||||||
using ManagementBaseObject? wmiParameters = arguments.Length == 0 ? null :
|
using var wmiParameters = arguments.Length == 0 ? null :
|
||||||
this.GetMethodParameters(this.wmiClass, methodName, methodParameters, arguments);
|
this.GetMethodParameters(this.wmiClass, methodName, methodParameters, arguments);
|
||||||
using ManagementBaseObject result = this.wmiClass.InvokeMethod(methodName, wmiParameters, null);
|
using var result = this.wmiClass.InvokeMethod(methodName, wmiParameters, null);
|
||||||
this.CheckError(result);
|
this.CheckError(result);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ namespace WMI
|
||||||
public T GetCollection<T>()
|
public T GetCollection<T>()
|
||||||
where T : IWmiCollection
|
where T : IWmiCollection
|
||||||
{
|
{
|
||||||
WmiClassName className = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
|
var className = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
|
||||||
|
|
||||||
return (T)ProxyFactory.Create(new ClassHandler(this.wmiScope, className.Name), typeof(T), true);
|
return (T)ProxyFactory.Create(new ClassHandler(this.wmiScope, className.Name), typeof(T), true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ namespace WinSW.Plugins
|
||||||
{
|
{
|
||||||
const int BaseBufferSize = 0x1000;
|
const int BaseBufferSize = 0x1000;
|
||||||
string variableKey = '\0' + variable + '=';
|
string variableKey = '\0' + variable + '=';
|
||||||
string buffer = new string('\0', BaseBufferSize + variableKey.Length);
|
string buffer = new('\0', BaseBufferSize + variableKey.Length);
|
||||||
fixed (char* bufferPtr = buffer)
|
fixed (char* bufferPtr = buffer)
|
||||||
{
|
{
|
||||||
long startAddress = address;
|
long startAddress = address;
|
||||||
|
@ -171,7 +171,7 @@ namespace WinSW.Plugins
|
||||||
_ = NtWow64QueryInformationProcess64(
|
_ = NtWow64QueryInformationProcess64(
|
||||||
processHandle,
|
processHandle,
|
||||||
PROCESSINFOCLASS.ProcessBasicInformation,
|
PROCESSINFOCLASS.ProcessBasicInformation,
|
||||||
out PROCESS_BASIC_INFORMATION64 information,
|
out var information,
|
||||||
sizeof(PROCESS_BASIC_INFORMATION64));
|
sizeof(PROCESS_BASIC_INFORMATION64));
|
||||||
|
|
||||||
PEB64 peb;
|
PEB64 peb;
|
||||||
|
@ -190,7 +190,7 @@ namespace WinSW.Plugins
|
||||||
this.StopParentProcessFirst = bool.Parse(XmlHelper.SingleElement(node, "stopParentFirst", false)!);
|
this.StopParentProcessFirst = bool.Parse(XmlHelper.SingleElement(node, "stopParentFirst", false)!);
|
||||||
this.ServiceId = descriptor.Id;
|
this.ServiceId = descriptor.Id;
|
||||||
// TODO: Consider making it documented
|
// TODO: Consider making it documented
|
||||||
var checkWinSWEnvironmentVariable = XmlHelper.SingleElement(node, "checkWinSWEnvironmentVariable", true);
|
string? checkWinSWEnvironmentVariable = XmlHelper.SingleElement(node, "checkWinSWEnvironmentVariable", true);
|
||||||
this.CheckWinSWEnvironmentVariable = checkWinSWEnvironmentVariable is null ? true : bool.Parse(checkWinSWEnvironmentVariable);
|
this.CheckWinSWEnvironmentVariable = checkWinSWEnvironmentVariable is null ? true : bool.Parse(checkWinSWEnvironmentVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ namespace WinSW.Plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill the runaway process
|
// Kill the runaway process
|
||||||
StringBuilder bldr = new StringBuilder("Stopping the runaway process (pid=");
|
var bldr = new StringBuilder("Stopping the runaway process (pid=");
|
||||||
bldr.Append(pid);
|
bldr.Append(pid);
|
||||||
bldr.Append(") and its children. Environment was ");
|
bldr.Append(") and its children. Environment was ");
|
||||||
if (!this.CheckWinSWEnvironmentVariable)
|
if (!this.CheckWinSWEnvironmentVariable)
|
||||||
|
|
|
@ -10,8 +10,8 @@ namespace WinSW.Plugins
|
||||||
{
|
{
|
||||||
public class SharedDirectoryMapper : AbstractWinSWExtension
|
public class SharedDirectoryMapper : AbstractWinSWExtension
|
||||||
{
|
{
|
||||||
private readonly SharedDirectoryMappingHelper _mapper = new SharedDirectoryMappingHelper();
|
private readonly SharedDirectoryMappingHelper _mapper = new();
|
||||||
private readonly List<SharedDirectoryMapperConfig> _entries = new List<SharedDirectoryMapperConfig>();
|
private readonly List<SharedDirectoryMapperConfig> _entries = new();
|
||||||
|
|
||||||
public override string DisplayName => "Shared Directory Mapper";
|
public override string DisplayName => "Shared Directory Mapper";
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@ namespace WinSW.Plugins
|
||||||
|
|
||||||
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(IWinSWConfiguration descriptor, XmlNode node)
|
public override void Configure(IWinSWConfiguration descriptor, 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++)
|
||||||
|
@ -47,14 +47,14 @@ namespace WinSW.Plugins
|
||||||
{
|
{
|
||||||
var dict = config.GetSettings();
|
var dict = config.GetSettings();
|
||||||
|
|
||||||
var mappingNode = dict["mapping"];
|
object mappingNode = dict["mapping"];
|
||||||
|
|
||||||
if (!(mappingNode is List<object> mappings))
|
if (!(mappingNode is List<object> mappings))
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("SharedDirectoryMapper mapping should be a list");
|
throw new InvalidDataException("SharedDirectoryMapper mapping should be a list");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var map in mappings)
|
foreach (object map in mappings)
|
||||||
{
|
{
|
||||||
var mapConfig = SharedDirectoryMapperConfig.FromYaml(map);
|
var mapConfig = SharedDirectoryMapperConfig.FromYaml(map);
|
||||||
this._entries.Add(mapConfig);
|
this._entries.Add(mapConfig);
|
||||||
|
@ -63,7 +63,7 @@ namespace WinSW.Plugins
|
||||||
|
|
||||||
public override void OnWrapperStarted()
|
public override void OnWrapperStarted()
|
||||||
{
|
{
|
||||||
foreach (SharedDirectoryMapperConfig config in this._entries)
|
foreach (var config in this._entries)
|
||||||
{
|
{
|
||||||
if (config.EnableMapping)
|
if (config.EnableMapping)
|
||||||
{
|
{
|
||||||
|
@ -86,7 +86,7 @@ namespace WinSW.Plugins
|
||||||
|
|
||||||
public override void BeforeWrapperStopped()
|
public override void BeforeWrapperStopped()
|
||||||
{
|
{
|
||||||
foreach (SharedDirectoryMapperConfig config in this._entries)
|
foreach (var config in this._entries)
|
||||||
{
|
{
|
||||||
if (config.EnableMapping)
|
if (config.EnableMapping)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace WinSW.Plugins
|
||||||
/// <exception cref="MapperException">Operation failure</exception>
|
/// <exception cref="MapperException">Operation failure</exception>
|
||||||
private void InvokeCommand(string command, string args)
|
private void InvokeCommand(string command, string args)
|
||||||
{
|
{
|
||||||
Process p = new Process
|
var p = new Process
|
||||||
{
|
{
|
||||||
StartInfo =
|
StartInfo =
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace winswTests.Configuration
|
||||||
[Test]
|
[Test]
|
||||||
public void AllOptionsConfigShouldDeclareDefaults()
|
public void AllOptionsConfigShouldDeclareDefaults()
|
||||||
{
|
{
|
||||||
ServiceDescriptor desc = Load("allOptions");
|
var desc = Load("allOptions");
|
||||||
|
|
||||||
Assert.That(desc.Id, Is.EqualTo("myapp"));
|
Assert.That(desc.Id, Is.EqualTo("myapp"));
|
||||||
Assert.That(desc.Caption, Is.EqualTo("MyApp Service (powered by WinSW)"));
|
Assert.That(desc.Caption, Is.EqualTo("MyApp Service (powered by WinSW)"));
|
||||||
|
@ -30,7 +30,7 @@ namespace winswTests.Configuration
|
||||||
[Test]
|
[Test]
|
||||||
public void MinimalConfigShouldDeclareDefaults()
|
public void MinimalConfigShouldDeclareDefaults()
|
||||||
{
|
{
|
||||||
ServiceDescriptor desc = Load("minimal");
|
var desc = Load("minimal");
|
||||||
|
|
||||||
Assert.That(desc.Id, Is.EqualTo("myapp"));
|
Assert.That(desc.Id, Is.EqualTo("myapp"));
|
||||||
Assert.That(desc.Caption, Is.EqualTo("MyApp Service (powered by WinSW)"));
|
Assert.That(desc.Caption, Is.EqualTo("MyApp Service (powered by WinSW)"));
|
||||||
|
@ -57,7 +57,7 @@ namespace winswTests.Configuration
|
||||||
string path = Path.Combine(directory, $@"examples\sample-{exampleName}.xml");
|
string path = Path.Combine(directory, $@"examples\sample-{exampleName}.xml");
|
||||||
Assert.That(path, Does.Exist);
|
Assert.That(path, Does.Exist);
|
||||||
|
|
||||||
XmlDocument dom = new XmlDocument();
|
var dom = new XmlDocument();
|
||||||
dom.Load(path);
|
dom.Load(path);
|
||||||
return new ServiceDescriptor(dom);
|
return new ServiceDescriptor(dom);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace winswTests
|
||||||
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 sd = ConfigXmlBuilder.create()
|
var sd = ConfigXmlBuilder.create()
|
||||||
.WithDownload(d)
|
.WithDownload(d)
|
||||||
.ToServiceDescriptor(true);
|
.ToServiceDescriptor(true);
|
||||||
|
@ -33,7 +33,7 @@ namespace winswTests
|
||||||
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 sd = ConfigXmlBuilder.create()
|
var sd = ConfigXmlBuilder.create()
|
||||||
.WithDownload(d)
|
.WithDownload(d)
|
||||||
.ToServiceDescriptor(true);
|
.ToServiceDescriptor(true);
|
||||||
|
@ -51,7 +51,7 @@ namespace winswTests
|
||||||
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 sd = ConfigXmlBuilder.create()
|
var sd = ConfigXmlBuilder.create()
|
||||||
.WithDownload(d)
|
.WithDownload(d)
|
||||||
.ToServiceDescriptor(true);
|
.ToServiceDescriptor(true);
|
||||||
|
@ -98,7 +98,7 @@ namespace winswTests
|
||||||
[TestCase(false)]
|
[TestCase(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 sd = ConfigXmlBuilder.create()
|
var sd = ConfigXmlBuilder.create()
|
||||||
.WithDownload(d)
|
.WithDownload(d)
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace winswTests
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class DownloadTests
|
public class DownloadTests
|
||||||
{
|
{
|
||||||
private readonly HttpListener globalListener = new HttpListener();
|
private readonly HttpListener globalListener = new();
|
||||||
|
|
||||||
private readonly byte[] contents = { 0x57, 0x69, 0x6e, 0x53, 0x57 };
|
private readonly byte[] contents = { 0x57, 0x69, 0x6e, 0x53, 0x57 };
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ namespace winswTests
|
||||||
[OneTimeSetUp]
|
[OneTimeSetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
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}/";
|
||||||
|
@ -44,7 +44,7 @@ namespace winswTests
|
||||||
|
|
||||||
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;
|
||||||
|
@ -77,7 +77,7 @@ namespace winswTests
|
||||||
|
|
||||||
async Task ListenAsync()
|
async Task ListenAsync()
|
||||||
{
|
{
|
||||||
HttpListenerContext context = await listener.GetContextAsync();
|
var context = await listener.GetContextAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
server(context);
|
server(context);
|
||||||
|
@ -141,7 +141,7 @@ namespace winswTests
|
||||||
},
|
},
|
||||||
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;
|
||||||
|
@ -157,8 +157,8 @@ namespace winswTests
|
||||||
[Test]
|
[Test]
|
||||||
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) =>
|
||||||
|
@ -185,7 +185,7 @@ namespace winswTests
|
||||||
[Test]
|
[Test]
|
||||||
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) =>
|
||||||
|
@ -215,7 +215,7 @@ namespace winswTests
|
||||||
await this.TestClientServerAsync(
|
await this.TestClientServerAsync(
|
||||||
async (source, dest) =>
|
async (source, dest) =>
|
||||||
{
|
{
|
||||||
WebException exception = await AsyncAssert.ThrowsAsync<WebException>(
|
var exception = await AsyncAssert.ThrowsAsync<WebException>(
|
||||||
async () => await new Download(source, dest).PerformAsync());
|
async () => await new Download(source, dest).PerformAsync());
|
||||||
|
|
||||||
Assert.That(exception.Status, Is.EqualTo(WebExceptionStatus.ProtocolError));
|
Assert.That(exception.Status, Is.EqualTo(WebExceptionStatus.ProtocolError));
|
||||||
|
|
|
@ -68,7 +68,7 @@ extensions:
|
||||||
[Test]
|
[Test]
|
||||||
public void LoadExtensions()
|
public void LoadExtensions()
|
||||||
{
|
{
|
||||||
WinSWExtensionManager manager = new WinSWExtensionManager(this._testServiceDescriptor);
|
var manager = new WinSWExtensionManager(this._testServiceDescriptor);
|
||||||
manager.LoadExtensions();
|
manager.LoadExtensions();
|
||||||
Assert.AreEqual(1, manager.Extensions.Count, "One extension should be loaded");
|
Assert.AreEqual(1, manager.Extensions.Count, "One extension should be loaded");
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ extensions:
|
||||||
[Test]
|
[Test]
|
||||||
public void LoadExtensionsYaml()
|
public void LoadExtensionsYaml()
|
||||||
{
|
{
|
||||||
WinSWExtensionManager manager = new WinSWExtensionManager(this._testServiceDescriptorYaml);
|
var manager = new WinSWExtensionManager(this._testServiceDescriptorYaml);
|
||||||
manager.LoadExtensions();
|
manager.LoadExtensions();
|
||||||
Assert.AreEqual(1, manager.Extensions.Count, "One extension should be loaded");
|
Assert.AreEqual(1, manager.Extensions.Count, "One extension should be loaded");
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ extensions:
|
||||||
[Test]
|
[Test]
|
||||||
public void StartStopExtension()
|
public void StartStopExtension()
|
||||||
{
|
{
|
||||||
WinSWExtensionManager manager = new WinSWExtensionManager(this._testServiceDescriptor);
|
var manager = new WinSWExtensionManager(this._testServiceDescriptor);
|
||||||
manager.LoadExtensions();
|
manager.LoadExtensions();
|
||||||
manager.FireOnWrapperStarted();
|
manager.FireOnWrapperStarted();
|
||||||
manager.FireBeforeWrapperStopped();
|
manager.FireBeforeWrapperStopped();
|
||||||
|
@ -109,12 +109,12 @@ extensions:
|
||||||
{
|
{
|
||||||
Assert.Ignore();
|
Assert.Ignore();
|
||||||
|
|
||||||
var winswId = "myAppWithRunaway";
|
string winswId = "myAppWithRunaway";
|
||||||
var extensionId = "runawayProcessKiller";
|
string extensionId = "runawayProcessKiller";
|
||||||
var tmpDir = FilesystemTestHelper.CreateTmpDirectory();
|
string tmpDir = FilesystemTestHelper.CreateTmpDirectory();
|
||||||
|
|
||||||
// Spawn the test process
|
// Spawn the test process
|
||||||
Process proc = new Process();
|
var proc = new Process();
|
||||||
var ps = proc.StartInfo;
|
var ps = proc.StartInfo;
|
||||||
ps.FileName = "cmd.exe";
|
ps.FileName = "cmd.exe";
|
||||||
ps.Arguments = "/c pause";
|
ps.Arguments = "/c pause";
|
||||||
|
@ -126,11 +126,11 @@ extensions:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Generate extension and ensure that the roundtrip is correct
|
// Generate extension and ensure that the roundtrip is correct
|
||||||
var pidfile = Path.Combine(tmpDir, "process.pid");
|
string pidfile = Path.Combine(tmpDir, "process.pid");
|
||||||
var sd = ConfigXmlBuilder.create(id: winswId)
|
var sd = ConfigXmlBuilder.create(id: winswId)
|
||||||
.WithRunawayProcessKiller(new RunawayProcessKillerExtension(pidfile), extensionId)
|
.WithRunawayProcessKiller(new RunawayProcessKillerExtension(pidfile), extensionId)
|
||||||
.ToServiceDescriptor();
|
.ToServiceDescriptor();
|
||||||
WinSWExtensionManager manager = new WinSWExtensionManager(sd);
|
var manager = new WinSWExtensionManager(sd);
|
||||||
manager.LoadExtensions();
|
manager.LoadExtensions();
|
||||||
var extension = manager.Extensions[extensionId] as RunawayProcessKillerExtension;
|
var extension = manager.Extensions[extensionId] as RunawayProcessKillerExtension;
|
||||||
Assert.IsNotNull(extension, "RunawayProcessKillerExtension should be loaded");
|
Assert.IsNotNull(extension, "RunawayProcessKillerExtension should be loaded");
|
||||||
|
|
|
@ -84,7 +84,7 @@ extensions:
|
||||||
[Test]
|
[Test]
|
||||||
public void LoadExtensions()
|
public void LoadExtensions()
|
||||||
{
|
{
|
||||||
WinSWExtensionManager manager = new WinSWExtensionManager(this._testServiceDescriptor);
|
var manager = new WinSWExtensionManager(this._testServiceDescriptor);
|
||||||
manager.LoadExtensions();
|
manager.LoadExtensions();
|
||||||
Assert.AreEqual(2, manager.Extensions.Count, "Two extensions should be loaded");
|
Assert.AreEqual(2, manager.Extensions.Count, "Two extensions should be loaded");
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ extensions:
|
||||||
[Test]
|
[Test]
|
||||||
public void LoadExtensionsYaml()
|
public void LoadExtensionsYaml()
|
||||||
{
|
{
|
||||||
WinSWExtensionManager manager = new WinSWExtensionManager(this._testServiceDescriptorYaml);
|
var manager = new WinSWExtensionManager(this._testServiceDescriptorYaml);
|
||||||
manager.LoadExtensions();
|
manager.LoadExtensions();
|
||||||
Assert.AreEqual(2, manager.Extensions.Count, "Two extensions should be loaded");
|
Assert.AreEqual(2, manager.Extensions.Count, "Two extensions should be loaded");
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ extensions:
|
||||||
[Test]
|
[Test]
|
||||||
public void StartStopExtension()
|
public void StartStopExtension()
|
||||||
{
|
{
|
||||||
WinSWExtensionManager manager = new WinSWExtensionManager(this._testServiceDescriptor);
|
var manager = new WinSWExtensionManager(this._testServiceDescriptor);
|
||||||
manager.LoadExtensions();
|
manager.LoadExtensions();
|
||||||
manager.FireOnWrapperStarted();
|
manager.FireOnWrapperStarted();
|
||||||
manager.FireBeforeWrapperStopped();
|
manager.FireBeforeWrapperStopped();
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace winswTests
|
||||||
{
|
{
|
||||||
_ = CLITestHelper.CLITest(new[] { "install" });
|
_ = CLITestHelper.CLITest(new[] { "install" });
|
||||||
|
|
||||||
using ServiceController controller = new ServiceController(CLITestHelper.Id);
|
using var controller = new ServiceController(CLITestHelper.Id);
|
||||||
Assert.That(controller.DisplayName, Is.EqualTo(CLITestHelper.Name));
|
Assert.That(controller.DisplayName, Is.EqualTo(CLITestHelper.Name));
|
||||||
Assert.That(controller.CanStop, Is.False);
|
Assert.That(controller.CanStop, Is.False);
|
||||||
Assert.That(controller.CanShutdown, Is.False);
|
Assert.That(controller.CanShutdown, Is.False);
|
||||||
|
@ -61,7 +61,7 @@ namespace winswTests
|
||||||
{
|
{
|
||||||
const string commandName = "nonExistentCommand";
|
const string commandName = "nonExistentCommand";
|
||||||
string expectedMessage = "Unknown command: " + commandName;
|
string expectedMessage = "Unknown command: " + commandName;
|
||||||
CLITestResult result = CLITestHelper.CLIErrorTest(new[] { commandName });
|
var result = CLITestHelper.CLIErrorTest(new[] { commandName });
|
||||||
|
|
||||||
Assert.That(result.HasException, Is.True);
|
Assert.That(result.HasException, Is.True);
|
||||||
Assert.That(result.Out, Does.Contain(expectedMessage));
|
Assert.That(result.Out, Does.Contain(expectedMessage));
|
||||||
|
|
|
@ -463,7 +463,7 @@ delayedAutoStart: true";
|
||||||
[Test]
|
[Test]
|
||||||
public void Must_Specify_Values_Test()
|
public void Must_Specify_Values_Test()
|
||||||
{
|
{
|
||||||
var yml = @"
|
string yml = @"
|
||||||
name: This is a test
|
name: This is a test
|
||||||
executable: 'C:\Program Files\Java\jdk1.8.0_241\bin\java.exe'
|
executable: 'C:\Program Files\Java\jdk1.8.0_241\bin\java.exe'
|
||||||
description: This is test winsw";
|
description: This is test winsw";
|
||||||
|
|
|
@ -36,11 +36,11 @@ $@"<service>
|
||||||
/// <exception cref="Exception">Command failure</exception>
|
/// <exception cref="Exception">Command failure</exception>
|
||||||
public static string CLITest(string[] arguments, ServiceDescriptor descriptor = null)
|
public static string CLITest(string[] arguments, ServiceDescriptor descriptor = null)
|
||||||
{
|
{
|
||||||
TextWriter tmpOut = Console.Out;
|
var tmpOut = Console.Out;
|
||||||
TextWriter tmpErr = Console.Error;
|
var tmpErr = Console.Error;
|
||||||
|
|
||||||
using StringWriter swOut = new StringWriter();
|
using var swOut = new StringWriter();
|
||||||
using StringWriter swErr = new StringWriter();
|
using var swErr = new StringWriter();
|
||||||
|
|
||||||
Console.SetOut(swOut);
|
Console.SetOut(swOut);
|
||||||
Console.SetError(swErr);
|
Console.SetError(swErr);
|
||||||
|
@ -68,11 +68,11 @@ $@"<service>
|
||||||
public static CLITestResult CLIErrorTest(string[] arguments, ServiceDescriptor descriptor = null)
|
public static CLITestResult CLIErrorTest(string[] arguments, ServiceDescriptor descriptor = null)
|
||||||
{
|
{
|
||||||
Exception testEx = null;
|
Exception testEx = null;
|
||||||
TextWriter tmpOut = Console.Out;
|
var tmpOut = Console.Out;
|
||||||
TextWriter tmpErr = Console.Error;
|
var tmpErr = Console.Error;
|
||||||
|
|
||||||
using StringWriter swOut = new StringWriter();
|
using var swOut = new StringWriter();
|
||||||
using StringWriter swErr = new StringWriter();
|
using var swErr = new StringWriter();
|
||||||
|
|
||||||
Console.SetOut(swOut);
|
Console.SetOut(swOut);
|
||||||
Console.SetError(swErr);
|
Console.SetError(swErr);
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace winswTests.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
|
||||||
|
@ -111,8 +111,8 @@ namespace winswTests.Util
|
||||||
|
|
||||||
public ConfigXmlBuilder WithRunawayProcessKiller(RunawayProcessKillerExtension ext, string extensionId = "killRunawayProcess", bool enabled = true)
|
public ConfigXmlBuilder WithRunawayProcessKiller(RunawayProcessKillerExtension ext, string extensionId = "killRunawayProcess", bool enabled = true)
|
||||||
{
|
{
|
||||||
var fullyQualifiedExtensionName = ExtensionTestBase.GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension));
|
string fullyQualifiedExtensionName = ExtensionTestBase.GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension));
|
||||||
StringBuilder str = new StringBuilder();
|
var str = new StringBuilder();
|
||||||
str.AppendFormat(" <extension enabled=\"{0}\" className=\"{1}\" id=\"{2}\">\n", new object[] { enabled, fullyQualifiedExtensionName, extensionId });
|
str.AppendFormat(" <extension enabled=\"{0}\" className=\"{1}\" id=\"{2}\">\n", new object[] { enabled, fullyQualifiedExtensionName, extensionId });
|
||||||
str.AppendFormat(" <pidfile>{0}</pidfile>\n", ext.Pidfile);
|
str.AppendFormat(" <pidfile>{0}</pidfile>\n", ext.Pidfile);
|
||||||
str.AppendFormat(" <stopTimeout>{0}</stopTimeout>\n", ext.StopTimeout.TotalMilliseconds);
|
str.AppendFormat(" <stopTimeout>{0}</stopTimeout>\n", ext.StopTimeout.TotalMilliseconds);
|
||||||
|
@ -126,7 +126,7 @@ namespace winswTests.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
|
||||||
|
|
|
@ -26,11 +26,11 @@ namespace winswTests.Util
|
||||||
/// <returns>Dictionary of the strings.</returns>
|
/// <returns>Dictionary of the strings.</returns>
|
||||||
public static Dictionary<string, string> parseSetOutput(string filePath)
|
public static Dictionary<string, string> parseSetOutput(string filePath)
|
||||||
{
|
{
|
||||||
Dictionary<string, string> res = new Dictionary<string, string>();
|
var res = new Dictionary<string, string>();
|
||||||
var lines = File.ReadAllLines(filePath);
|
string[] lines = File.ReadAllLines(filePath);
|
||||||
foreach (var line in lines)
|
foreach (string line in lines)
|
||||||
{
|
{
|
||||||
var parsed = line.Split("=".ToCharArray(), 2);
|
string[] parsed = line.Split("=".ToCharArray(), 2);
|
||||||
if (parsed.Length == 2)
|
if (parsed.Length == 2)
|
||||||
{
|
{
|
||||||
res.Add(parsed[0], parsed[1]);
|
res.Add(parsed[0], parsed[1]);
|
||||||
|
|
|
@ -20,17 +20,17 @@ namespace winswTests.Util
|
||||||
|
|
||||||
Environment.SetEnvironmentVariable("TEST_KEY", "TEST_VALUE");
|
Environment.SetEnvironmentVariable("TEST_KEY", "TEST_VALUE");
|
||||||
|
|
||||||
var tmpDir = FilesystemTestHelper.CreateTmpDirectory();
|
string tmpDir = FilesystemTestHelper.CreateTmpDirectory();
|
||||||
string envFile = Path.Combine(tmpDir, "env.properties");
|
string envFile = Path.Combine(tmpDir, "env.properties");
|
||||||
string scriptFile = Path.Combine(tmpDir, "printenv.bat");
|
string scriptFile = Path.Combine(tmpDir, "printenv.bat");
|
||||||
File.WriteAllText(scriptFile, "set > " + envFile);
|
File.WriteAllText(scriptFile, "set > " + envFile);
|
||||||
|
|
||||||
Process proc = new Process();
|
var proc = new Process();
|
||||||
var ps = proc.StartInfo;
|
var ps = proc.StartInfo;
|
||||||
ps.FileName = scriptFile;
|
ps.FileName = scriptFile;
|
||||||
|
|
||||||
ProcessHelper.StartProcessAndCallbackForExit(proc);
|
ProcessHelper.StartProcessAndCallbackForExit(proc);
|
||||||
var exited = proc.WaitForExit(5000);
|
bool exited = proc.WaitForExit(5000);
|
||||||
if (!exited)
|
if (!exited)
|
||||||
{
|
{
|
||||||
Assert.Fail("Process " + proc + " didn't exit after 5 seconds");
|
Assert.Fail("Process " + proc + " didn't exit after 5 seconds");
|
||||||
|
@ -50,17 +50,17 @@ namespace winswTests.Util
|
||||||
[Test]
|
[Test]
|
||||||
public void ShouldNotHangWhenWritingLargeStringToStdOut()
|
public void ShouldNotHangWhenWritingLargeStringToStdOut()
|
||||||
{
|
{
|
||||||
var tmpDir = FilesystemTestHelper.CreateTmpDirectory();
|
string tmpDir = FilesystemTestHelper.CreateTmpDirectory();
|
||||||
string scriptFile = Path.Combine(tmpDir, "print_lots_to_stdout.bat");
|
string scriptFile = Path.Combine(tmpDir, "print_lots_to_stdout.bat");
|
||||||
var lotsOfStdOut = string.Join(string.Empty, Enumerable.Range(1, 1000));
|
string lotsOfStdOut = string.Join(string.Empty, Enumerable.Range(1, 1000));
|
||||||
File.WriteAllText(scriptFile, $"echo \"{lotsOfStdOut}\"");
|
File.WriteAllText(scriptFile, $"echo \"{lotsOfStdOut}\"");
|
||||||
|
|
||||||
Process proc = new Process();
|
var proc = new Process();
|
||||||
var ps = proc.StartInfo;
|
var ps = proc.StartInfo;
|
||||||
ps.FileName = scriptFile;
|
ps.FileName = scriptFile;
|
||||||
|
|
||||||
ProcessHelper.StartProcessAndCallbackForExit(proc);
|
ProcessHelper.StartProcessAndCallbackForExit(proc);
|
||||||
var exited = proc.WaitForExit(5000);
|
bool exited = proc.WaitForExit(5000);
|
||||||
if (!exited)
|
if (!exited)
|
||||||
{
|
{
|
||||||
Assert.Fail("Process " + proc + " didn't exit after 5 seconds");
|
Assert.Fail("Process " + proc + " didn't exit after 5 seconds");
|
||||||
|
|
|
@ -13,10 +13,10 @@ namespace winswTests.Util
|
||||||
|
|
||||||
public static void AssertPropertyIsDefault(ServiceDescriptor desc, string property)
|
public static void AssertPropertyIsDefault(ServiceDescriptor desc, string property)
|
||||||
{
|
{
|
||||||
PropertyInfo actualProperty = typeof(ServiceDescriptor).GetProperty(property);
|
var actualProperty = typeof(ServiceDescriptor).GetProperty(property);
|
||||||
Assert.That(actualProperty, Is.Not.Null);
|
Assert.That(actualProperty, Is.Not.Null);
|
||||||
|
|
||||||
PropertyInfo defaultProperty = typeof(DefaultWinSWSettings).GetProperty(property);
|
var defaultProperty = typeof(DefaultWinSWSettings).GetProperty(property);
|
||||||
Assert.That(defaultProperty, Is.Not.Null);
|
Assert.That(defaultProperty, Is.Not.Null);
|
||||||
|
|
||||||
Assert.That(actualProperty.GetValue(desc, null), Is.EqualTo(defaultProperty.GetValue(ServiceDescriptor.Defaults, null)));
|
Assert.That(actualProperty.GetValue(desc, null), Is.EqualTo(defaultProperty.GetValue(ServiceDescriptor.Defaults, null)));
|
||||||
|
@ -24,7 +24,7 @@ namespace winswTests.Util
|
||||||
|
|
||||||
public static void AssertPropertyIsDefault(ServiceDescriptor desc, List<string> properties)
|
public static void AssertPropertyIsDefault(ServiceDescriptor desc, List<string> properties)
|
||||||
{
|
{
|
||||||
foreach (var prop in properties)
|
foreach (string prop in properties)
|
||||||
{
|
{
|
||||||
AssertPropertyIsDefault(desc, prop);
|
AssertPropertyIsDefault(desc, prop);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace WinSW.Logging
|
||||||
|
|
||||||
public EventLog? Locate()
|
public EventLog? Locate()
|
||||||
{
|
{
|
||||||
WrapperService? service = this.Service;
|
var service = this.Service;
|
||||||
if (service != null && !service.IsShuttingDown)
|
if (service != null && !service.IsShuttingDown)
|
||||||
{
|
{
|
||||||
return service.EventLog;
|
return service.EventLog;
|
||||||
|
|
|
@ -87,8 +87,8 @@ namespace WinSW
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get service info for the future use
|
// Get service info for the future use
|
||||||
IWin32Services svcs = new WmiRoot().GetCollection<IWin32Services>();
|
var svcs = new WmiRoot().GetCollection<IWin32Services>();
|
||||||
IWin32Service? svc = svcs.Select(descriptor.Id);
|
var svc = svcs.Select(descriptor.Id);
|
||||||
|
|
||||||
var args = new List<string>(Array.AsReadOnly(argsArray));
|
var args = new List<string>(Array.AsReadOnly(argsArray));
|
||||||
if (args[0] == "/redirect")
|
if (args[0] == "/redirect")
|
||||||
|
@ -182,9 +182,7 @@ namespace WinSW
|
||||||
default:
|
default:
|
||||||
Console.WriteLine("Unknown command: " + args[0]);
|
Console.WriteLine("Unknown command: " + args[0]);
|
||||||
PrintAvailableCommands();
|
PrintAvailableCommands();
|
||||||
#pragma warning disable S112 // General exceptions should never be thrown
|
|
||||||
throw new Exception("Unknown command: " + args[0]);
|
throw new Exception("Unknown command: " + args[0]);
|
||||||
#pragma warning restore S112 // General exceptions should never be thrown
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Install()
|
void Install()
|
||||||
|
@ -202,9 +200,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
Console.WriteLine("Service with id '" + descriptor.Id + "' already exists");
|
Console.WriteLine("Service with id '" + descriptor.Id + "' already exists");
|
||||||
Console.WriteLine("To install the service, delete the existing one or change service Id in the configuration file");
|
Console.WriteLine("To install the service, delete the existing one or change service Id in the configuration file");
|
||||||
#pragma warning disable S112 // General exceptions should never be thrown
|
|
||||||
throw new Exception("Installation failure: Service with id '" + descriptor.Id + "' already exists");
|
throw new Exception("Installation failure: Service with id '" + descriptor.Id + "' already exists");
|
||||||
#pragma warning restore S112 // General exceptions should never be thrown
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string? username = null;
|
string? username = null;
|
||||||
|
@ -252,12 +248,12 @@ namespace WinSW
|
||||||
password,
|
password,
|
||||||
descriptor.ServiceDependencies);
|
descriptor.ServiceDependencies);
|
||||||
|
|
||||||
using ServiceManager scm = ServiceManager.Open();
|
using var scm = ServiceManager.Open();
|
||||||
using Service sc = scm.OpenService(descriptor.Id);
|
using var sc = scm.OpenService(descriptor.Id);
|
||||||
|
|
||||||
sc.SetDescription(descriptor.Description);
|
sc.SetDescription(descriptor.Description);
|
||||||
|
|
||||||
SC_ACTION[] actions = descriptor.FailureActions;
|
var actions = descriptor.FailureActions;
|
||||||
if (actions.Length > 0)
|
if (actions.Length > 0)
|
||||||
{
|
{
|
||||||
sc.SetFailureActions(descriptor.ResetFailureAfter, actions);
|
sc.SetFailureActions(descriptor.ResetFailureAfter, actions);
|
||||||
|
@ -460,18 +456,14 @@ namespace WinSW
|
||||||
bool result = ProcessApis.CreateProcess(null, descriptor.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, ProcessApis.CREATE_NEW_PROCESS_GROUP, IntPtr.Zero, null, default, out _);
|
bool result = ProcessApis.CreateProcess(null, descriptor.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, ProcessApis.CREATE_NEW_PROCESS_GROUP, IntPtr.Zero, null, default, out _);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
#pragma warning disable S112 // General exceptions should never be thrown
|
|
||||||
throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
|
throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
|
||||||
#pragma warning restore S112 // General exceptions should never be thrown
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Status()
|
void Status()
|
||||||
{
|
{
|
||||||
Log.Debug("User requested the status of the process with id '" + descriptor.Id + "'");
|
Log.Debug("User requested the status of the process with id '" + descriptor.Id + "'");
|
||||||
#pragma warning disable S3358 // Ternary operators should not be nested
|
|
||||||
Console.WriteLine(svc is null ? "NonExistent" : svc.Started ? "Started" : "Stopped");
|
Console.WriteLine(svc is null ? "NonExistent" : svc.Started ? "Started" : "Stopped");
|
||||||
#pragma warning restore S3358 // Ternary operators should not be nested
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test()
|
void Test()
|
||||||
|
@ -482,7 +474,7 @@ namespace WinSW
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WrapperService wsvc = new WrapperService(descriptor);
|
var wsvc = new WrapperService(descriptor);
|
||||||
wsvc.RaiseOnStart(args.ToArray());
|
wsvc.RaiseOnStart(args.ToArray());
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
wsvc.RaiseOnStop();
|
wsvc.RaiseOnStop();
|
||||||
|
@ -496,7 +488,7 @@ namespace WinSW
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WrapperService wsvc = new WrapperService(descriptor);
|
var wsvc = new WrapperService(descriptor);
|
||||||
wsvc.RaiseOnStart(args.ToArray());
|
wsvc.RaiseOnStart(args.ToArray());
|
||||||
Console.WriteLine("Press any key to stop the service...");
|
Console.WriteLine("Press any key to stop the service...");
|
||||||
_ = Console.Read();
|
_ = Console.Read();
|
||||||
|
@ -506,9 +498,9 @@ namespace WinSW
|
||||||
// [DoesNotReturn]
|
// [DoesNotReturn]
|
||||||
void Elevate()
|
void Elevate()
|
||||||
{
|
{
|
||||||
using Process current = Process.GetCurrentProcess();
|
using var current = Process.GetCurrentProcess();
|
||||||
|
|
||||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
var startInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
UseShellExecute = true,
|
UseShellExecute = true,
|
||||||
Verb = "runas",
|
Verb = "runas",
|
||||||
|
@ -525,7 +517,7 @@ namespace WinSW
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using Process elevated = Process.Start(startInfo)!;
|
using var elevated = Process.Start(startInfo)!;
|
||||||
|
|
||||||
elevated.WaitForExit();
|
elevated.WaitForExit();
|
||||||
Environment.Exit(elevated.ExitCode);
|
Environment.Exit(elevated.ExitCode);
|
||||||
|
@ -544,18 +536,18 @@ namespace WinSW
|
||||||
private static void InitLoggers(IWinSWConfiguration descriptor, bool enableConsoleLogging)
|
private static void InitLoggers(IWinSWConfiguration descriptor, bool enableConsoleLogging)
|
||||||
{
|
{
|
||||||
// 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;
|
||||||
|
|
||||||
// Legacy format from winsw-1.x: (DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " - " + message);
|
// Legacy format from winsw-1.x: (DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " - " + message);
|
||||||
PatternLayout layout = new PatternLayout { ConversionPattern = "%d %-5p - %m%n" };
|
var layout = new PatternLayout { ConversionPattern = "%d %-5p - %m%n" };
|
||||||
layout.ActivateOptions();
|
layout.ActivateOptions();
|
||||||
|
|
||||||
List<IAppender> appenders = new List<IAppender>();
|
var appenders = new List<IAppender>();
|
||||||
|
|
||||||
// .wrapper.log
|
// .wrapper.log
|
||||||
string wrapperLogPath = Path.Combine(descriptor.LogDirectory, descriptor.BaseName + ".wrapper.log");
|
string wrapperLogPath = Path.Combine(descriptor.LogDirectory, descriptor.BaseName + ".wrapper.log");
|
||||||
|
@ -604,8 +596,8 @@ namespace WinSW
|
||||||
|
|
||||||
internal static unsafe bool IsProcessElevated()
|
internal static unsafe 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))
|
||||||
{
|
{
|
||||||
ThrowWin32Exception("Failed to open process token.");
|
ThrowWin32Exception("Failed to open process token.");
|
||||||
}
|
}
|
||||||
|
@ -615,7 +607,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 _))
|
||||||
{
|
{
|
||||||
|
@ -631,17 +623,17 @@ namespace WinSW
|
||||||
|
|
||||||
static void ThrowWin32Exception(string message)
|
static void ThrowWin32Exception(string message)
|
||||||
{
|
{
|
||||||
Win32Exception inner = new Win32Exception();
|
var inner = new Win32Exception();
|
||||||
throw new Win32Exception(inner.NativeErrorCode, message + ' ' + inner.Message);
|
throw new Win32Exception(inner.NativeErrorCode, message + ' ' + inner.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
@ -661,8 +653,8 @@ namespace WinSW
|
||||||
|
|
||||||
private static IWinSWConfiguration GetServiceDescriptor()
|
private static IWinSWConfiguration GetServiceDescriptor()
|
||||||
{
|
{
|
||||||
var executablePath = new DefaultWinSWSettings().ExecutablePath;
|
string executablePath = new DefaultWinSWSettings().ExecutablePath;
|
||||||
var baseName = Path.GetFileNameWithoutExtension(executablePath);
|
string baseName = Path.GetFileNameWithoutExtension(executablePath);
|
||||||
|
|
||||||
var d = new DirectoryInfo(Path.GetDirectoryName(executablePath)!);
|
var d = new DirectoryInfo(Path.GetDirectoryName(executablePath)!);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
private ServiceApis.SERVICE_STATUS wrapperServiceStatus;
|
private ServiceApis.SERVICE_STATUS wrapperServiceStatus;
|
||||||
|
|
||||||
private readonly Process process = new Process();
|
private readonly Process process = new();
|
||||||
|
|
||||||
private readonly IWinSWConfiguration descriptor;
|
private readonly IWinSWConfiguration descriptor;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace WinSW
|
||||||
#endif
|
#endif
|
||||||
"WinSW");
|
"WinSW");
|
||||||
|
|
||||||
internal static readonly WrapperServiceEventLogProvider eventLogProvider = new WrapperServiceEventLogProvider();
|
internal static readonly WrapperServiceEventLogProvider eventLogProvider = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates to the watch dog thread that we are going to terminate the process,
|
/// Indicates to the watch dog thread that we are going to terminate the process,
|
||||||
|
@ -79,7 +79,7 @@ namespace WinSW
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void HandleFileCopies()
|
private void HandleFileCopies()
|
||||||
{
|
{
|
||||||
var file = this.descriptor.BasePath + ".copies";
|
string file = this.descriptor.BasePath + ".copies";
|
||||||
if (!File.Exists(file))
|
if (!File.Exists(file))
|
||||||
{
|
{
|
||||||
return; // nothing to handle
|
return; // nothing to handle
|
||||||
|
@ -136,7 +136,7 @@ namespace WinSW
|
||||||
Directory.CreateDirectory(logDirectory);
|
Directory.CreateDirectory(logDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogHandler logAppender = this.descriptor.Log.CreateLogHandler();
|
var logAppender = this.descriptor.Log.CreateLogHandler();
|
||||||
|
|
||||||
logAppender.EventLogger = this;
|
logAppender.EventLogger = this;
|
||||||
return logAppender;
|
return logAppender;
|
||||||
|
@ -198,11 +198,11 @@ namespace WinSW
|
||||||
|
|
||||||
// handle downloads
|
// handle downloads
|
||||||
#if VNEXT
|
#if VNEXT
|
||||||
List<Download> downloads = this.descriptor.Downloads;
|
var downloads = this.descriptor.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()}";
|
||||||
this.LogEvent(downloadMessage);
|
this.LogEvent(downloadMessage);
|
||||||
Log.Info(downloadMessage);
|
Log.Info(downloadMessage);
|
||||||
|
@ -215,14 +215,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!;
|
||||||
this.LogEvent($"{errorMessage}. {exception.Message}");
|
this.LogEvent($"{errorMessage}. {exception.Message}");
|
||||||
Log.Error(errorMessage, exception);
|
Log.Error(errorMessage, exception);
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ namespace WinSW
|
||||||
throw new AggregateException(exceptions);
|
throw new AggregateException(exceptions);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
foreach (Download download in this.descriptor.Downloads)
|
foreach (var download in this.descriptor.Downloads)
|
||||||
{
|
{
|
||||||
string downloadMessage = $"Downloading: {download.From} to {download.To}. failOnError={download.FailOnError.ToString()}";
|
string downloadMessage = $"Downloading: {download.From} to {download.To}. failOnError={download.FailOnError.ToString()}";
|
||||||
this.LogEvent(downloadMessage);
|
this.LogEvent(downloadMessage);
|
||||||
|
@ -286,7 +286,7 @@ namespace WinSW
|
||||||
this.ExtensionManager.LoadExtensions();
|
this.ExtensionManager.LoadExtensions();
|
||||||
this.ExtensionManager.FireOnWrapperStarted();
|
this.ExtensionManager.FireOnWrapperStarted();
|
||||||
|
|
||||||
LogHandler executableLogHandler = this.CreateExecutableLogHandler();
|
var executableLogHandler = this.CreateExecutableLogHandler();
|
||||||
this.StartProcess(this.process, startArguments, this.descriptor.Executable, executableLogHandler, true);
|
this.StartProcess(this.process, startArguments, this.descriptor.Executable, executableLogHandler, true);
|
||||||
this.ExtensionManager.FireOnProcessStarted(this.process);
|
this.ExtensionManager.FireOnProcessStarted(this.process);
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ namespace WinSW
|
||||||
|
|
||||||
stopArguments += " " + this.descriptor.Arguments;
|
stopArguments += " " + this.descriptor.Arguments;
|
||||||
|
|
||||||
Process stopProcess = new Process();
|
var stopProcess = new Process();
|
||||||
string? executable = this.descriptor.StopExecutable;
|
string? executable = this.descriptor.StopExecutable;
|
||||||
|
|
||||||
executable ??= this.descriptor.Executable;
|
executable ??= this.descriptor.Executable;
|
||||||
|
@ -432,7 +432,7 @@ namespace WinSW
|
||||||
|
|
||||||
private void SignalShutdownComplete()
|
private void SignalShutdownComplete()
|
||||||
{
|
{
|
||||||
IntPtr handle = this.ServiceHandle;
|
var handle = this.ServiceHandle;
|
||||||
this.wrapperServiceStatus.CheckPoint++;
|
this.wrapperServiceStatus.CheckPoint++;
|
||||||
// WriteEvent("SignalShutdownComplete " + wrapperServiceStatus.checkPoint + ":" + wrapperServiceStatus.waitHint);
|
// WriteEvent("SignalShutdownComplete " + wrapperServiceStatus.checkPoint + ":" + wrapperServiceStatus.waitHint);
|
||||||
this.wrapperServiceStatus.CurrentState = ServiceApis.ServiceState.STOPPED;
|
this.wrapperServiceStatus.CurrentState = ServiceApis.ServiceState.STOPPED;
|
||||||
|
|
Loading…
Reference in New Issue