mirror of https://github.com/winsw/winsw
Fix inconsistencies in YAML config (#678)
parent
027a8d30e3
commit
11d09aa6ae
|
@ -175,8 +175,8 @@
|
|||
"description": "Optionally specify the order of service shutdown. If configed as true, parent process is shutdown first",
|
||||
"$ref": "#/definitions/boolPattern"
|
||||
},
|
||||
"resetFailureAfter": {
|
||||
"$id": "#/properties/resetFailureAfter",
|
||||
"resetFailure": {
|
||||
"$id": "#/properties/resetFailure",
|
||||
"description": "This optional element controls the timing in which Windows SCM resets the failure count.",
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ executable: java
|
|||
# delay: 20 sec
|
||||
# -
|
||||
# action: reboot
|
||||
#resetFailureAfter: 01:00:00
|
||||
#resetFailure: 01:00:00
|
||||
#securityDescriptor: security descriptor string
|
||||
#arguments: >
|
||||
# -classpath
|
||||
|
|
|
@ -78,10 +78,10 @@ namespace WinSW.Configuration
|
|||
|
||||
public ServiceAccount ServiceAccount => new()
|
||||
{
|
||||
ServiceAccountName = null,
|
||||
ServiceAccountDomain = null,
|
||||
ServiceAccountPassword = null,
|
||||
AllowServiceAcountLogonRight = false
|
||||
User = null,
|
||||
Domain = null,
|
||||
Password = null,
|
||||
AllowServiceLogonRight = false
|
||||
};
|
||||
|
||||
public class LogDefaults : Log
|
||||
|
|
|
@ -1,29 +1,23 @@
|
|||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace WinSW.Configuration
|
||||
namespace WinSW.Configuration
|
||||
{
|
||||
public class ServiceAccount
|
||||
{
|
||||
[YamlMember(Alias = "user")]
|
||||
public string? ServiceAccountName { get; set; }
|
||||
public string? User { get; set; }
|
||||
|
||||
[YamlMember(Alias = "domain")]
|
||||
public string? ServiceAccountDomain { get; set; }
|
||||
public string? Domain { get; set; }
|
||||
|
||||
[YamlMember(Alias = "password")]
|
||||
public string? ServiceAccountPassword { get; set; }
|
||||
public string? Password { get; set; }
|
||||
|
||||
[YamlMember(Alias = "allowservicelogon")]
|
||||
public bool AllowServiceAcountLogonRight { get; set; }
|
||||
public bool AllowServiceLogonRight { get; set; }
|
||||
|
||||
public string? ServiceAccountUser
|
||||
public string? FullUser
|
||||
{
|
||||
get => this.ServiceAccountName is null ? null : (this.ServiceAccountDomain ?? ".") + "\\" + this.ServiceAccountName;
|
||||
get => this.User is null ? null : (this.Domain ?? ".") + "\\" + this.User;
|
||||
}
|
||||
|
||||
public bool HasServiceAccount()
|
||||
{
|
||||
return !string.IsNullOrEmpty(this.ServiceAccountName);
|
||||
return !string.IsNullOrEmpty(this.User);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -572,9 +572,9 @@ namespace WinSW
|
|||
string action = node.Attributes!["action"]?.Value ?? throw new InvalidDataException("'action' is missing");
|
||||
var type = action switch
|
||||
{
|
||||
"restart" => SC_ACTION_TYPE.SC_ACTION_RESTART,
|
||||
"none" => SC_ACTION_TYPE.SC_ACTION_NONE,
|
||||
"reboot" => SC_ACTION_TYPE.SC_ACTION_REBOOT,
|
||||
"restart" => SC_ACTION_TYPE.RESTART,
|
||||
"none" => SC_ACTION_TYPE.NONE,
|
||||
"reboot" => SC_ACTION_TYPE.REBOOT,
|
||||
_ => throw new Exception("Invalid failure action: " + action)
|
||||
};
|
||||
var delay = node.Attributes["delay"];
|
||||
|
@ -621,15 +621,15 @@ namespace WinSW
|
|||
|
||||
var serviceAccount = Defaults.ServiceAccount;
|
||||
|
||||
serviceAccount.ServiceAccountDomain = this.GetServiceAccountPart(node, "domain");
|
||||
serviceAccount.Domain = this.GetServiceAccountPart(node, "domain");
|
||||
|
||||
serviceAccount.ServiceAccountName = this.GetServiceAccountPart(node, "user");
|
||||
serviceAccount.User = this.GetServiceAccountPart(node, "user");
|
||||
|
||||
serviceAccount.ServiceAccountPassword = this.GetServiceAccountPart(node, "password");
|
||||
serviceAccount.Password = this.GetServiceAccountPart(node, "password");
|
||||
|
||||
string? loginRight = this.GetServiceAccountPart(node, "allowservicelogon");
|
||||
|
||||
serviceAccount.AllowServiceAcountLogonRight = this.ParseAllowServiceAcountLogonRight(loginRight);
|
||||
serviceAccount.AllowServiceLogonRight = this.ParseAllowServiceAcountLogonRight(loginRight);
|
||||
|
||||
return serviceAccount;
|
||||
}
|
||||
|
|
|
@ -2,629 +2,214 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
#if VNEXT
|
||||
using System.Runtime.CompilerServices;
|
||||
#endif
|
||||
using System.ServiceProcess;
|
||||
using System.Xml;
|
||||
using WinSW.Native;
|
||||
using WinSW.Util;
|
||||
using YamlDotNet.Serialization;
|
||||
using static System.Environment;
|
||||
using static WinSW.Download;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
||||
namespace WinSW.Configuration
|
||||
{
|
||||
public class YamlServiceConfig : IServiceConfig
|
||||
{
|
||||
private readonly DefaultSettings defaults;
|
||||
private readonly RawYamlServiceConfig raw;
|
||||
|
||||
public YamlServiceConfig()
|
||||
public YamlServiceConfig(string baseName, string directory)
|
||||
{
|
||||
this.defaults = new DefaultSettings();
|
||||
this.BaseName = this.defaults.BaseName;
|
||||
this.BasePath = this.defaults.BasePath;
|
||||
|
||||
this.BaseName = baseName;
|
||||
this.BasePath = Path.Combine(directory, baseName);
|
||||
|
||||
using (var reader = new StreamReader(this.BasePath + ".yml"))
|
||||
{
|
||||
var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
|
||||
this.raw = deserializer.Deserialize<RawYamlServiceConfig>(reader);
|
||||
}
|
||||
|
||||
[YamlMember(Alias = "id")]
|
||||
public string? IdYaml { get; set; }
|
||||
Environment.SetEnvironmentVariable("BASE", directory);
|
||||
|
||||
[YamlMember(Alias = "name")]
|
||||
public string? NameYaml { get; set; }
|
||||
// ditto for ID
|
||||
Environment.SetEnvironmentVariable("SERVICE_ID", this.Name);
|
||||
|
||||
[YamlMember(Alias = "description")]
|
||||
public string? DescriptionYaml { get; set; }
|
||||
// New name
|
||||
Environment.SetEnvironmentVariable(WinSWSystem.EnvVarNameExecutablePath, this.ExecutablePath);
|
||||
|
||||
[YamlMember(Alias = "executable")]
|
||||
public string? ExecutableYaml { get; set; }
|
||||
// Also inject system environment variables
|
||||
Environment.SetEnvironmentVariable(WinSWSystem.EnvVarNameServiceId, this.Name);
|
||||
|
||||
[YamlMember(Alias = "executablePath")]
|
||||
public string? ExecutablePathYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "hideWindow")]
|
||||
public bool? HideWindowYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "workingdirectory")]
|
||||
public string? WorkingDirectoryYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "serviceaccount")]
|
||||
public ServiceAccount? ServiceAccountYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "log")]
|
||||
public YamlLog? YAMLLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "download")]
|
||||
public List<YamlDownload>? DownloadsYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "arguments")]
|
||||
public string? ArgumentsYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "startArguments")]
|
||||
public string? StartArgumentsYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "stopArguments")]
|
||||
public string? StopArgumentsYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "stopExecutable")]
|
||||
public string? StopExecutableYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "stopParentProcessFirst")]
|
||||
public bool? StopParentProcessFirstYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "resetFailureAfter")]
|
||||
public string? ResetFailureAfterYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "stopTimeout")]
|
||||
public string? StopTimeoutYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "startMode")]
|
||||
public string? StartModeYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "serviceDependencies")]
|
||||
public string[]? ServiceDependenciesYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "waitHint")]
|
||||
public string? WaitHintYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "sleepTime")]
|
||||
public string? SleepTimeYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "interactive")]
|
||||
public bool? InteractiveYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "priority")]
|
||||
public string? PriorityYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "beepOnShutdown")]
|
||||
public bool BeepOnShutdown { get; set; }
|
||||
|
||||
[YamlMember(Alias = "env")]
|
||||
public List<YamlEnv>? EnvironmentVariablesYaml { get; set; }
|
||||
|
||||
[YamlMember(Alias = "onFailure")]
|
||||
public List<YamlFailureAction>? YamlFailureActions { get; set; }
|
||||
|
||||
[YamlMember(Alias = "delayedAutoStart")]
|
||||
public bool DelayedAutoStart { get; set; }
|
||||
|
||||
[YamlMember(Alias = "securityDescriptor")]
|
||||
public string? SecurityDescriptorYaml { get; set; }
|
||||
|
||||
public class YamlEnv
|
||||
{
|
||||
[YamlMember(Alias = "name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[YamlMember(Alias = "value")]
|
||||
public string? Value { get; set; }
|
||||
this.LoadEnvironmentVariables();
|
||||
}
|
||||
|
||||
public class YamlLog : Log
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
private YamlServiceConfig(RawYamlServiceConfig raw)
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
{
|
||||
private readonly YamlServiceConfig configs;
|
||||
|
||||
public YamlLog()
|
||||
{
|
||||
this.configs = new YamlServiceConfig();
|
||||
this.defaults = new DefaultSettings();
|
||||
this.raw = raw;
|
||||
}
|
||||
|
||||
[YamlMember(Alias = "mode")]
|
||||
public string? ModeYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "name")]
|
||||
public string? NameYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "sizeThreshold")]
|
||||
public int? SizeThresholdYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "keepFiles")]
|
||||
public int? KeepFilesYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "pattern")]
|
||||
public string? PatternYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "period")]
|
||||
public int? PeriodYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "logpath")]
|
||||
public string? LogPathYamlLog { get; set; }
|
||||
|
||||
// Filters
|
||||
[YamlMember(Alias = "outFileDisabled")]
|
||||
public bool? OutFileDisabledYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "errFileDisabled")]
|
||||
public bool? ErrFileDisabledYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "outFilePattern")]
|
||||
public string? OutFilePatternYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "errFilePattern")]
|
||||
public string? ErrFilePatternYamlLog { get; set; }
|
||||
|
||||
// Zip options
|
||||
[YamlMember(Alias = "autoRollAtTime")]
|
||||
public string? AutoRollAtTimeYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "zipOlderThanNumDays")]
|
||||
public string? ZipOlderThanNumDaysYamlLog { get; set; }
|
||||
|
||||
[YamlMember(Alias = "zipDateFormat")]
|
||||
public string? ZipDateFormatYamlLog { get; set; }
|
||||
|
||||
public override string Mode => this.ModeYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.Mode :
|
||||
this.ModeYamlLog;
|
||||
|
||||
public override string Name
|
||||
public static YamlServiceConfig FromYaml(string yaml)
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.NameYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.Name :
|
||||
ExpandEnvironmentVariables(this.NameYamlLog);
|
||||
}
|
||||
var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
|
||||
var raw = deserializer.Deserialize<RawYamlServiceConfig>(yaml);
|
||||
return new(raw);
|
||||
}
|
||||
|
||||
public override string Directory
|
||||
private static string? Expand(string? value) => value is null ? null : Environment.ExpandEnvironmentVariables(value);
|
||||
|
||||
private static bool? ExpandBoolean(string? value) => value is null ? null : ConfigHelper.YamlBoolParse(Environment.ExpandEnvironmentVariables(value));
|
||||
|
||||
private static TimeSpan? ExpandTimeSpan(string? value) => value is null ? null : ConfigHelper.ParseTimeSpan(Environment.ExpandEnvironmentVariables(value));
|
||||
|
||||
private static T? ExpandEnum<T>(
|
||||
string? value,
|
||||
#if VNEXT
|
||||
[CallerMemberName] string? name = null)
|
||||
#else
|
||||
string? name = null)
|
||||
#endif
|
||||
where T : unmanaged, Enum
|
||||
{
|
||||
get
|
||||
if (value is null)
|
||||
{
|
||||
return this.LogPathYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.Directory :
|
||||
ExpandEnvironmentVariables(this.LogPathYamlLog);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override int? SizeThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.SizeThresholdYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.SizeThreshold :
|
||||
this.SizeThresholdYamlLog;
|
||||
}
|
||||
}
|
||||
|
||||
public override int? KeepFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.KeepFilesYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.KeepFiles :
|
||||
this.KeepFilesYamlLog;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Pattern
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.PatternYamlLog != null)
|
||||
{
|
||||
return this.PatternYamlLog;
|
||||
}
|
||||
|
||||
return DefaultSettings.DefaultLogSettings.Pattern;
|
||||
}
|
||||
}
|
||||
|
||||
public override int? Period => this.PeriodYamlLog is null ? 1 : this.PeriodYamlLog;
|
||||
|
||||
public override bool OutFileDisabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.OutFileDisabledYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.OutFileDisabled :
|
||||
(bool)this.OutFileDisabledYamlLog;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ErrFileDisabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ErrFileDisabledYamlLog is null ?
|
||||
this.configs.defaults.ErrFileDisabled :
|
||||
(bool)this.ErrFileDisabledYamlLog;
|
||||
}
|
||||
}
|
||||
|
||||
public override string OutFilePattern
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.OutFilePatternYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.OutFilePattern :
|
||||
ExpandEnvironmentVariables(this.OutFilePatternYamlLog);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ErrFilePattern
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ErrFilePatternYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.ErrFilePattern :
|
||||
ExpandEnvironmentVariables(this.ErrFilePatternYamlLog);
|
||||
}
|
||||
}
|
||||
|
||||
public override string? AutoRollAtTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.AutoRollAtTimeYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.AutoRollAtTime :
|
||||
this.AutoRollAtTimeYamlLog;
|
||||
}
|
||||
}
|
||||
|
||||
public override int? ZipOlderThanNumDays
|
||||
{
|
||||
get
|
||||
{
|
||||
int? zipolderthannumdays = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(this.ZipOlderThanNumDaysYamlLog))
|
||||
{
|
||||
if (!int.TryParse(this.ZipOlderThanNumDaysYamlLog, out int zipolderthannumdaysValue))
|
||||
{
|
||||
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but zipOlderThanNumDays does not match the int format found in configuration XML.");
|
||||
}
|
||||
|
||||
zipolderthannumdays = zipolderthannumdaysValue;
|
||||
}
|
||||
|
||||
return zipolderthannumdays;
|
||||
}
|
||||
}
|
||||
|
||||
public override string? ZipDateFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ZipDateFormatYamlLog is null ?
|
||||
DefaultSettings.DefaultLogSettings.ZipDateFormat :
|
||||
this.ZipDateFormatYamlLog;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class YamlDownload
|
||||
{
|
||||
[YamlMember(Alias = "from")]
|
||||
public string FromYamlDownload { get; set; } = string.Empty;
|
||||
|
||||
[YamlMember(Alias = "to")]
|
||||
public string ToYamlDownload { get; set; } = string.Empty;
|
||||
|
||||
[YamlMember(Alias = "auth")]
|
||||
public string? AuthYamlDownload { get; set; }
|
||||
|
||||
[YamlMember(Alias = "username")]
|
||||
public string? UsernameYamlDownload { get; set; }
|
||||
|
||||
[YamlMember(Alias = "password")]
|
||||
public string? PasswordYamlDownload { get; set; }
|
||||
|
||||
[YamlMember(Alias = "unsecureAuth")]
|
||||
public bool UnsecureAuthYamlDownload { get; set; }
|
||||
|
||||
[YamlMember(Alias = "failOnError")]
|
||||
public bool FailOnErrorYamlDownload { get; set; }
|
||||
|
||||
[YamlMember(Alias = "proxy")]
|
||||
public string? ProxyYamlDownload { get; set; }
|
||||
|
||||
public string FromDownload => ExpandEnvironmentVariables(this.FromYamlDownload);
|
||||
|
||||
public string ToDownload => ExpandEnvironmentVariables(this.ToYamlDownload);
|
||||
|
||||
public string? UsernameDownload => this.UsernameYamlDownload is null ? null : ExpandEnvironmentVariables(this.UsernameYamlDownload);
|
||||
|
||||
public string? PasswordDownload => this.PasswordYamlDownload is null ? null : ExpandEnvironmentVariables(this.PasswordYamlDownload);
|
||||
|
||||
public string? ProxyDownload => this.ProxyYamlDownload is null ? null : ExpandEnvironmentVariables(this.ProxyYamlDownload);
|
||||
|
||||
public AuthType AuthDownload
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.AuthYamlDownload is null)
|
||||
{
|
||||
return AuthType.None;
|
||||
}
|
||||
|
||||
string auth = ExpandEnvironmentVariables(this.AuthYamlDownload);
|
||||
|
||||
try
|
||||
{
|
||||
return (AuthType)Enum.Parse(typeof(AuthType), auth, true);
|
||||
return (T)Enum.Parse(typeof(T), value, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Auth type in YAML must be one of the following:");
|
||||
foreach (string at in Enum.GetNames(typeof(AuthType)))
|
||||
{
|
||||
Console.WriteLine(at);
|
||||
}
|
||||
|
||||
Console.WriteLine($"'{name ?? typeof(T).FullName}' in YAML must be one of the followings: {string.Join(", ", Enum.GetNames(typeof(T)))}.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class YamlFailureAction
|
||||
{
|
||||
[YamlMember(Alias = "action")]
|
||||
public string? FailureAction { get; set; }
|
||||
public string Name => Expand(this.raw.Id) ?? this.defaults.Name;
|
||||
|
||||
[YamlMember(Alias = "delay")]
|
||||
public string? FailureActionDelay { get; set; }
|
||||
public string Description => Expand(this.raw.Description) ?? this.defaults.Description;
|
||||
|
||||
public SC_ACTION_TYPE Type
|
||||
{
|
||||
get
|
||||
{
|
||||
var actionType = this.FailureAction switch
|
||||
{
|
||||
"restart" => SC_ACTION_TYPE.SC_ACTION_RESTART,
|
||||
"none" => SC_ACTION_TYPE.SC_ACTION_NONE,
|
||||
"reboot" => SC_ACTION_TYPE.SC_ACTION_REBOOT,
|
||||
_ => throw new InvalidDataException("Invalid failure action: " + this.FailureAction)
|
||||
};
|
||||
public string Executable => Expand(this.raw.Executable) ?? this.defaults.Executable;
|
||||
|
||||
return actionType;
|
||||
}
|
||||
}
|
||||
public string ExecutablePath => this.defaults.ExecutablePath;
|
||||
|
||||
public TimeSpan Delay => this.FailureActionDelay is null ? TimeSpan.Zero : ConfigHelper.ParseTimeSpan(this.FailureActionDelay);
|
||||
}
|
||||
public string DisplayName => Expand(this.raw.Name) ?? this.defaults.DisplayName;
|
||||
|
||||
private string? GetArguments(string? args, ArgType type)
|
||||
{
|
||||
if (args is null)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ArgType.Arg:
|
||||
return this.defaults.Arguments;
|
||||
case ArgType.Startarg:
|
||||
return this.defaults.StartArguments;
|
||||
case ArgType.Stoparg:
|
||||
return this.defaults.StopArguments;
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
public bool HideWindow => ExpandBoolean(this.raw.HideWindow) ?? this.defaults.HideWindow;
|
||||
|
||||
return ExpandEnvironmentVariables(args);
|
||||
}
|
||||
public bool StopParentProcessFirst => ExpandBoolean(this.raw.StopParentProcessFirst) ?? this.defaults.StopParentProcessFirst;
|
||||
|
||||
private enum ArgType
|
||||
{
|
||||
Arg = 0,
|
||||
Startarg = 1,
|
||||
Stoparg = 2
|
||||
}
|
||||
public ServiceStartMode StartMode => ExpandEnum<ServiceStartMode>(this.raw.StartMode) ?? this.defaults.StartMode;
|
||||
|
||||
private List<Download> GetDownloads(List<YamlDownload>? downloads)
|
||||
{
|
||||
if (downloads is null)
|
||||
{
|
||||
return this.defaults.Downloads;
|
||||
}
|
||||
public bool DelayedAutoStart => ExpandBoolean(this.raw.DelayedAutoStart) ?? this.defaults.DelayedAutoStart;
|
||||
|
||||
var result = new List<Download>(downloads.Count);
|
||||
public bool BeepOnShutdown => ExpandBoolean(this.raw.BeepOnShutdown) ?? this.defaults.BeepOnShutdown;
|
||||
|
||||
foreach (var item in downloads)
|
||||
{
|
||||
result.Add(new Download(
|
||||
item.FromDownload,
|
||||
item.ToDownload,
|
||||
item.FailOnErrorYamlDownload,
|
||||
item.AuthDownload,
|
||||
item.UsernameDownload,
|
||||
item.PasswordDownload,
|
||||
item.UnsecureAuthYamlDownload,
|
||||
item.ProxyDownload));
|
||||
}
|
||||
public string Arguments => Expand(this.raw.Arguments) ?? this.defaults.Arguments;
|
||||
|
||||
return result;
|
||||
}
|
||||
public string? StartArguments => Expand(this.raw.StartArguments) ?? this.defaults.StartArguments;
|
||||
|
||||
public string Name => this.IdYaml is null ? this.defaults.Name : ExpandEnvironmentVariables(this.IdYaml);
|
||||
public string? StopArguments => Expand(this.raw.StopArguments) ?? this.defaults.StopArguments;
|
||||
|
||||
public string Description => this.DescriptionYaml is null ? this.defaults.Description : ExpandEnvironmentVariables(this.DescriptionYaml);
|
||||
|
||||
public string Executable => this.ExecutableYaml is null ? this.defaults.Executable : ExpandEnvironmentVariables(this.ExecutableYaml);
|
||||
|
||||
public string ExecutablePath => this.ExecutablePathYaml is null ?
|
||||
this.defaults.ExecutablePath :
|
||||
ExpandEnvironmentVariables(this.ExecutablePathYaml);
|
||||
|
||||
public string DisplayName => this.NameYaml is null ? this.defaults.DisplayName : ExpandEnvironmentVariables(this.NameYaml);
|
||||
|
||||
public bool HideWindow => this.HideWindowYaml is null ? this.defaults.HideWindow : (bool)this.HideWindowYaml;
|
||||
|
||||
public bool StopParentProcessFirst
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.StopParentProcessFirstYaml is null ?
|
||||
this.defaults.StopParentProcessFirst :
|
||||
(bool)this.StopParentProcessFirstYaml;
|
||||
}
|
||||
}
|
||||
|
||||
public ServiceStartMode StartMode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.StartModeYaml is null)
|
||||
{
|
||||
return this.defaults.StartMode;
|
||||
}
|
||||
|
||||
string p = ExpandEnvironmentVariables(this.StartModeYaml);
|
||||
|
||||
try
|
||||
{
|
||||
return (ServiceStartMode)Enum.Parse(typeof(ServiceStartMode), p, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Start mode in YAML must be one of the following:");
|
||||
foreach (string sm in Enum.GetNames(typeof(ServiceStartMode)))
|
||||
{
|
||||
Console.WriteLine(sm);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Arguments
|
||||
{
|
||||
get
|
||||
{
|
||||
string? args = this.GetArguments(this.ArgumentsYaml, ArgType.Arg);
|
||||
return args is null ? this.defaults.Arguments : args;
|
||||
}
|
||||
}
|
||||
|
||||
public string? StartArguments => this.GetArguments(this.StartArgumentsYaml, ArgType.Startarg);
|
||||
|
||||
public string? StopArguments => this.GetArguments(this.StopArgumentsYaml, ArgType.Stoparg);
|
||||
|
||||
public string? StopExecutable
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.StopExecutableYaml is null ?
|
||||
this.defaults.StopExecutable :
|
||||
ExpandEnvironmentVariables(this.StopExecutableYaml);
|
||||
}
|
||||
}
|
||||
public string? StopExecutable => Expand(this.raw.StopExecutable) ?? this.defaults.StopExecutable;
|
||||
|
||||
public SC_ACTION[] FailureActions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.YamlFailureActions is null)
|
||||
if (this.raw.OnFailure is null)
|
||||
{
|
||||
#if VNEXT
|
||||
return Array.Empty<SC_ACTION>();
|
||||
#else
|
||||
return new SC_ACTION[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
var arr = new List<SC_ACTION>();
|
||||
var result = new SC_ACTION[this.raw.OnFailure.Count];
|
||||
|
||||
foreach (var item in this.YamlFailureActions)
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
arr.Add(new SC_ACTION(item.Type, item.Delay));
|
||||
var item = new YamlFailureAction(this.raw.OnFailure[i]);
|
||||
result[i] = new(item.Type, item.Delay);
|
||||
}
|
||||
|
||||
return arr.ToArray();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan ResetFailureAfter => this.ResetFailureAfterYaml is null ?
|
||||
this.defaults.ResetFailureAfter :
|
||||
ConfigHelper.ParseTimeSpan(this.ResetFailureAfterYaml);
|
||||
public TimeSpan ResetFailureAfter => ExpandTimeSpan(this.raw.ResetFailure) ?? this.defaults.ResetFailureAfter;
|
||||
|
||||
public string WorkingDirectory => this.WorkingDirectoryYaml is null ?
|
||||
this.defaults.WorkingDirectory :
|
||||
ExpandEnvironmentVariables(this.WorkingDirectoryYaml);
|
||||
public string WorkingDirectory => Expand(this.raw.WorkingDirectory) ?? this.defaults.WorkingDirectory;
|
||||
|
||||
public ProcessPriorityClass Priority
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.PriorityYaml is null)
|
||||
{
|
||||
return this.defaults.Priority;
|
||||
}
|
||||
public ProcessPriorityClass Priority => ExpandEnum<ProcessPriorityClass>(this.raw.Priority) ?? this.defaults.Priority;
|
||||
|
||||
string p = ExpandEnvironmentVariables(this.PriorityYaml);
|
||||
|
||||
try
|
||||
{
|
||||
return (ProcessPriorityClass)Enum.Parse(typeof(ProcessPriorityClass), p, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Priority in YAML must be one of the following:");
|
||||
foreach (string pr in Enum.GetNames(typeof(ProcessPriorityClass)))
|
||||
{
|
||||
Console.WriteLine(pr);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan StopTimeout => this.StopTimeoutYaml is null ? this.defaults.StopTimeout : ConfigHelper.ParseTimeSpan(this.StopTimeoutYaml);
|
||||
public TimeSpan StopTimeout => ExpandTimeSpan(this.raw.StopTimeout) ?? this.defaults.StopTimeout;
|
||||
|
||||
public string[] ServiceDependencies
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.ServiceDependenciesYaml is null)
|
||||
if (this.raw.Depend is null)
|
||||
{
|
||||
return this.defaults.ServiceDependencies;
|
||||
}
|
||||
|
||||
var result = new List<string>(0);
|
||||
string[] result = new string[this.raw.Depend.Length];
|
||||
|
||||
foreach (string item in this.ServiceDependenciesYaml)
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
result.Add(ExpandEnvironmentVariables(item));
|
||||
result[i] = Environment.ExpandEnvironmentVariables(this.raw.Depend[i]);
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan WaitHint => this.WaitHintYaml is null ? this.defaults.WaitHint : ConfigHelper.ParseTimeSpan(this.WaitHintYaml);
|
||||
public TimeSpan WaitHint => this.defaults.WaitHint;
|
||||
|
||||
public TimeSpan SleepTime => this.SleepTimeYaml is null ? this.defaults.SleepTime : ConfigHelper.ParseTimeSpan(this.SleepTimeYaml);
|
||||
public TimeSpan SleepTime => this.defaults.SleepTime;
|
||||
|
||||
public bool Interactive => this.InteractiveYaml is null ? this.defaults.Interactive : (bool)this.InteractiveYaml;
|
||||
public bool Interactive => ExpandBoolean(this.raw.Interactive) ?? this.defaults.Interactive;
|
||||
|
||||
public List<Download> Downloads => this.GetDownloads(this.DownloadsYaml);
|
||||
public List<Download> Downloads
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.raw.Download is null)
|
||||
{
|
||||
return this.defaults.Downloads;
|
||||
}
|
||||
|
||||
var result = new List<Download>(this.raw.Download.Count);
|
||||
|
||||
foreach (var item in this.raw.Download)
|
||||
{
|
||||
result.Add(new YamlDownload(item).Download);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, string> EnvironmentVariables { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
public void LoadEnvironmentVariables()
|
||||
{
|
||||
if (this.EnvironmentVariablesYaml is null)
|
||||
if (this.raw.Env is null)
|
||||
{
|
||||
this.EnvironmentVariables = this.defaults.EnvironmentVariables;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in this.EnvironmentVariablesYaml)
|
||||
|
||||
foreach (var item in this.raw.Env)
|
||||
{
|
||||
if (item.Name is null || item.Value is null)
|
||||
{
|
||||
|
@ -632,17 +217,34 @@ namespace WinSW.Configuration
|
|||
}
|
||||
|
||||
string key = item.Name;
|
||||
string value = ExpandEnvironmentVariables(item.Value);
|
||||
string value = Environment.ExpandEnvironmentVariables(item.Value);
|
||||
|
||||
this.EnvironmentVariables[key] = value;
|
||||
SetEnvironmentVariable(key, value);
|
||||
}
|
||||
Environment.SetEnvironmentVariable(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public ServiceAccount ServiceAccount => this.ServiceAccountYaml is null ? this.defaults.ServiceAccount : this.ServiceAccountYaml;
|
||||
public ServiceAccount ServiceAccount
|
||||
{
|
||||
get
|
||||
{
|
||||
var rawServiceAccount = this.raw.ServiceAccount;
|
||||
if (rawServiceAccount is null)
|
||||
{
|
||||
return this.defaults.ServiceAccount;
|
||||
}
|
||||
|
||||
public Log Log => this.YAMLLog is null ? this.defaults.Log : this.YAMLLog;
|
||||
return new()
|
||||
{
|
||||
User = Expand(rawServiceAccount.User),
|
||||
Domain = Expand(rawServiceAccount.Domain),
|
||||
Password = Expand(rawServiceAccount.Password),
|
||||
AllowServiceLogonRight = ExpandBoolean(rawServiceAccount.AllowServiceLogon) ?? false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public Log Log => this.raw.Log is null ? this.defaults.Log : new YamlLog(this.raw.Log);
|
||||
|
||||
public string LogDirectory => this.Log.Directory;
|
||||
|
||||
|
@ -650,9 +252,7 @@ namespace WinSW.Configuration
|
|||
|
||||
public XmlNode? XmlExtensions => null;
|
||||
|
||||
// YAML Extension
|
||||
[YamlMember(Alias = "extensions")]
|
||||
public List<YamlExtensionConfig>? YamlExtensions { get; set; }
|
||||
public List<YamlExtensionConfig>? YamlExtensions => this.raw.Extensions;
|
||||
|
||||
public List<string> ExtensionIds
|
||||
{
|
||||
|
@ -689,17 +289,158 @@ namespace WinSW.Configuration
|
|||
|
||||
public string BasePath { get; set; }
|
||||
|
||||
public string? SecurityDescriptor
|
||||
public string? SecurityDescriptor => Expand(this.raw.SecurityDescriptor) ?? this.defaults.SecurityDescriptor;
|
||||
|
||||
internal sealed class RawYamlServiceConfig
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.SecurityDescriptorYaml is null)
|
||||
{
|
||||
return this.defaults.SecurityDescriptor;
|
||||
public string? Id;
|
||||
public string? Name;
|
||||
public string? Description;
|
||||
public string? Executable;
|
||||
public string? HideWindow;
|
||||
public string? WorkingDirectory;
|
||||
public RawServiceAccount? ServiceAccount;
|
||||
public RawYamlLog? Log;
|
||||
public List<RawYamlDownload>? Download;
|
||||
public string? Arguments;
|
||||
public string? StartArguments;
|
||||
public string? StopArguments;
|
||||
public string? StopExecutable;
|
||||
public string? StopParentProcessFirst;
|
||||
public string? ResetFailure;
|
||||
public string? StopTimeout;
|
||||
public string? StartMode;
|
||||
public string[]? Depend;
|
||||
public string? Interactive;
|
||||
public string? Priority;
|
||||
public string? BeepOnShutdown;
|
||||
public List<RawYamlEnv>? Env;
|
||||
public List<RawYamlFailureAction>? OnFailure;
|
||||
public string? DelayedAutoStart;
|
||||
public string? SecurityDescriptor;
|
||||
public List<YamlExtensionConfig>? Extensions;
|
||||
}
|
||||
|
||||
return ExpandEnvironmentVariables(this.SecurityDescriptorYaml);
|
||||
}
|
||||
internal sealed class RawServiceAccount
|
||||
{
|
||||
public string? User;
|
||||
public string? Domain;
|
||||
public string? Password;
|
||||
public string? AllowServiceLogon;
|
||||
}
|
||||
|
||||
internal sealed class YamlLog : Log
|
||||
{
|
||||
private readonly DefaultSettings.LogDefaults defaults = new();
|
||||
private readonly RawYamlLog raw;
|
||||
|
||||
internal YamlLog(RawYamlLog raw) => this.raw = raw;
|
||||
|
||||
public override string Mode => Expand(this.raw.Mode) ?? this.defaults.Mode;
|
||||
|
||||
public override string Name => Expand(this.raw.Name) ?? this.defaults.Name;
|
||||
|
||||
public override string Directory => Expand(this.raw.LogPath) ?? this.defaults.Directory;
|
||||
|
||||
public override int? SizeThreshold => this.raw.SizeThreshold ?? this.defaults.SizeThreshold;
|
||||
|
||||
public override int? KeepFiles => this.raw.KeepFiles ?? this.defaults.KeepFiles;
|
||||
|
||||
public override string Pattern => Expand(this.raw.Pattern) ?? this.defaults.Pattern;
|
||||
|
||||
public override int? Period => this.raw.Period ?? this.defaults.Period;
|
||||
|
||||
public override bool OutFileDisabled => ExpandBoolean(this.raw.OutFileDisabled) ?? this.defaults.OutFileDisabled;
|
||||
|
||||
public override bool ErrFileDisabled => ExpandBoolean(this.raw.ErrFileDisabled) ?? this.defaults.ErrFileDisabled;
|
||||
|
||||
public override string OutFilePattern => Expand(this.raw.OutFilePattern) ?? this.defaults.OutFilePattern;
|
||||
|
||||
public override string ErrFilePattern => Expand(this.raw.ErrFilePattern) ?? this.defaults.ErrFilePattern;
|
||||
|
||||
public override string? AutoRollAtTime => Expand(this.raw.AutoRollAtTime) ?? this.defaults.AutoRollAtTime;
|
||||
|
||||
public override int? ZipOlderThanNumDays => this.raw.ZipOlderThanNumDays;
|
||||
|
||||
public override string? ZipDateFormat => Expand(this.raw.ZipDateFormat) ?? this.defaults.ZipDateFormat;
|
||||
}
|
||||
|
||||
internal sealed class RawYamlLog
|
||||
{
|
||||
public string? Mode;
|
||||
public string? Name;
|
||||
public int? SizeThreshold;
|
||||
public int? KeepFiles;
|
||||
public string? Pattern;
|
||||
public int? Period;
|
||||
public string? LogPath;
|
||||
public string? OutFileDisabled;
|
||||
public string? ErrFileDisabled;
|
||||
public string? OutFilePattern;
|
||||
public string? ErrFilePattern;
|
||||
public string? AutoRollAtTime;
|
||||
public int? ZipOlderThanNumDays;
|
||||
public string? ZipDateFormat;
|
||||
}
|
||||
|
||||
internal sealed class YamlDownload
|
||||
{
|
||||
private readonly RawYamlDownload raw;
|
||||
|
||||
internal YamlDownload(RawYamlDownload raw) => this.raw = raw;
|
||||
|
||||
public Download Download => new(this.From, this.To, this.FailOnError, this.Auth, this.Username, this.Password, this.UnsecureAuth, this.Proxy);
|
||||
|
||||
public string From => Expand(this.raw.From)!;
|
||||
|
||||
public string To => Expand(this.raw.To)!;
|
||||
|
||||
public string? Username => Expand(this.raw.Username);
|
||||
|
||||
public string? Password => Expand(this.raw.Password);
|
||||
|
||||
public bool UnsecureAuth => ExpandBoolean(this.raw.UnsecureAuth) ?? false;
|
||||
|
||||
public bool FailOnError => ExpandBoolean(this.raw.FailOnError) ?? false;
|
||||
|
||||
public string? Proxy => Expand(this.raw.Proxy);
|
||||
|
||||
public Download.AuthType Auth => ExpandEnum<Download.AuthType>(this.raw.Auth) ?? Download.AuthType.None;
|
||||
}
|
||||
|
||||
internal sealed class RawYamlDownload
|
||||
{
|
||||
public string From = string.Empty;
|
||||
public string To = string.Empty;
|
||||
public string? Auth;
|
||||
public string? Username;
|
||||
public string? Password;
|
||||
public string? UnsecureAuth;
|
||||
public string? FailOnError;
|
||||
public string? Proxy;
|
||||
}
|
||||
|
||||
internal sealed class RawYamlEnv
|
||||
{
|
||||
public string? Name;
|
||||
public string? Value;
|
||||
}
|
||||
|
||||
internal sealed class YamlFailureAction
|
||||
{
|
||||
private readonly RawYamlFailureAction raw;
|
||||
|
||||
internal YamlFailureAction(RawYamlFailureAction raw) => this.raw = raw;
|
||||
|
||||
public SC_ACTION_TYPE Type => ExpandEnum<SC_ACTION_TYPE>(this.raw.Action) ?? SC_ACTION_TYPE.NONE;
|
||||
|
||||
public TimeSpan Delay => ExpandTimeSpan(this.raw.Delay) ?? TimeSpan.Zero;
|
||||
}
|
||||
|
||||
internal sealed class RawYamlFailureAction
|
||||
{
|
||||
public string? Action;
|
||||
public string? Delay;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using WinSW.Configuration;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace WinSW
|
||||
{
|
||||
public class YamlServiceConfigLoader
|
||||
{
|
||||
public readonly YamlServiceConfig Config;
|
||||
|
||||
public YamlServiceConfigLoader(string baseName, string directory)
|
||||
{
|
||||
string basepath = Path.Combine(directory, baseName);
|
||||
|
||||
using (var reader = new StreamReader(basepath + ".yml"))
|
||||
{
|
||||
string file = reader.ReadToEnd();
|
||||
var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build();
|
||||
|
||||
this.Config = deserializer.Deserialize<YamlServiceConfig>(file);
|
||||
}
|
||||
|
||||
Environment.SetEnvironmentVariable("BASE", directory);
|
||||
|
||||
// ditto for ID
|
||||
Environment.SetEnvironmentVariable("SERVICE_ID", this.Config.Name);
|
||||
|
||||
// New name
|
||||
Environment.SetEnvironmentVariable(WinSWSystem.EnvVarNameExecutablePath, new DefaultSettings().ExecutablePath);
|
||||
|
||||
// Also inject system environment variables
|
||||
Environment.SetEnvironmentVariable(WinSWSystem.EnvVarNameServiceId, this.Config.Name);
|
||||
|
||||
this.Config.LoadEnvironmentVariables();
|
||||
}
|
||||
|
||||
public YamlServiceConfigLoader(YamlServiceConfig configs)
|
||||
{
|
||||
this.Config = configs;
|
||||
this.Config.LoadEnvironmentVariables();
|
||||
}
|
||||
|
||||
public static YamlServiceConfigLoader FromYaml(string yaml)
|
||||
{
|
||||
var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build();
|
||||
var configs = deserializer.Deserialize<YamlServiceConfig>(yaml);
|
||||
return new YamlServiceConfigLoader(configs);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -249,7 +249,7 @@ namespace WinSW.Extensions
|
|||
throw new ExtensionException(id, "Cannot load the class by name: " + className, ex);
|
||||
}
|
||||
|
||||
if (!(created is IWinSWExtension extension))
|
||||
if (created is not IWinSWExtension extension)
|
||||
{
|
||||
throw new ExtensionException(id, "The loaded class is not a WinSW extension: " + className + ". Type is " + created.GetType());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.ServiceProcess;
|
||||
using System.Text;
|
||||
|
@ -12,22 +11,22 @@ namespace WinSW.Native
|
|||
/// <summary>
|
||||
/// No action.
|
||||
/// </summary>
|
||||
SC_ACTION_NONE = 0,
|
||||
NONE = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Restart the service.
|
||||
/// </summary>
|
||||
SC_ACTION_RESTART = 1,
|
||||
RESTART = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Reboot the computer.
|
||||
/// </summary>
|
||||
SC_ACTION_REBOOT = 2,
|
||||
REBOOT = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Run a command.
|
||||
/// </summary>
|
||||
SC_ACTION_RUN_COMMAND = 3,
|
||||
RUN_COMMAND = 3,
|
||||
}
|
||||
|
||||
public struct SC_ACTION
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace WinSW.Plugins
|
|||
/// <summary>
|
||||
/// Absolute path to the PID file, which stores ID of the previously launched process.
|
||||
/// </summary>
|
||||
public string Pidfile { get; private set; }
|
||||
public string PidFile { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines the process termination timeout in milliseconds.
|
||||
|
@ -53,7 +53,7 @@ namespace WinSW.Plugins
|
|||
public RunawayProcessKillerExtension(string pidfile, int stopTimeoutMs = 5000, bool stopParentFirst = true, bool checkWinSWEnvironmentVariable = true)
|
||||
#pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable.
|
||||
{
|
||||
this.Pidfile = pidfile;
|
||||
this.PidFile = pidfile;
|
||||
this.StopTimeout = TimeSpan.FromMilliseconds(stopTimeoutMs);
|
||||
this.StopParentProcessFirst = stopParentFirst;
|
||||
this.CheckWinSWEnvironmentVariable = checkWinSWEnvironmentVariable;
|
||||
|
@ -184,7 +184,7 @@ namespace WinSW.Plugins
|
|||
{
|
||||
// We expect the upper logic to process any errors
|
||||
// TODO: a better parser API for types would be useful
|
||||
this.Pidfile = XmlHelper.SingleElement(node, "pidfile", false)!;
|
||||
this.PidFile = XmlHelper.SingleElement(node, "pidfile", false)!;
|
||||
this.StopTimeout = TimeSpan.FromMilliseconds(int.Parse(XmlHelper.SingleElement(node, "stopTimeout", false)!));
|
||||
this.StopParentProcessFirst = bool.Parse(XmlHelper.SingleElement(node, "stopParentFirst", false)!);
|
||||
this.ServiceId = descriptor.Name;
|
||||
|
@ -197,12 +197,12 @@ namespace WinSW.Plugins
|
|||
{
|
||||
var dict = config.GetSettings();
|
||||
|
||||
this.Pidfile = ExpandEnvironmentVariables((string)dict["pidfile"]);
|
||||
this.PidFile = ExpandEnvironmentVariables((string)dict["pidFile"]);
|
||||
|
||||
string stopTimeOutConfig = ExpandEnvironmentVariables((string)dict["stopTimeOut"]);
|
||||
string stopTimeOutConfig = ExpandEnvironmentVariables((string)dict["stopTimeout"]);
|
||||
this.StopTimeout = TimeSpan.FromMilliseconds(int.Parse(stopTimeOutConfig));
|
||||
|
||||
string StopParentProcessFirstConfig = ExpandEnvironmentVariables((string)dict["StopParentFirst"]);
|
||||
string StopParentProcessFirstConfig = ExpandEnvironmentVariables((string)dict["stopParentFirst"]);
|
||||
this.StopParentProcessFirst = bool.Parse(StopParentProcessFirstConfig);
|
||||
|
||||
try
|
||||
|
@ -224,16 +224,16 @@ namespace WinSW.Plugins
|
|||
{
|
||||
// Read PID file from the disk
|
||||
int pid;
|
||||
if (File.Exists(this.Pidfile))
|
||||
if (File.Exists(this.PidFile))
|
||||
{
|
||||
string pidstring;
|
||||
try
|
||||
{
|
||||
pidstring = File.ReadAllText(this.Pidfile);
|
||||
pidstring = File.ReadAllText(this.PidFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("Cannot read PID file from " + this.Pidfile, ex);
|
||||
Logger.Error("Cannot read PID file from " + this.PidFile, ex);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -243,13 +243,13 @@ namespace WinSW.Plugins
|
|||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Logger.Error("Invalid PID file number in '" + this.Pidfile + "'. The runaway process won't be checked", e);
|
||||
Logger.Error("Invalid PID file number in '" + this.PidFile + "'. The runaway process won't be checked", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Warn("The requested PID file '" + this.Pidfile + "' does not exist. The runaway process won't be checked");
|
||||
Logger.Warn("The requested PID file '" + this.PidFile + "' does not exist. The runaway process won't be checked");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -309,14 +309,14 @@ namespace WinSW.Plugins
|
|||
/// <param name="process"></param>
|
||||
public override void OnProcessStarted(Process process)
|
||||
{
|
||||
Logger.Info("Recording PID of the started process:" + process.Id + ". PID file destination is " + this.Pidfile);
|
||||
Logger.Info("Recording PID of the started process:" + process.Id + ". PID file destination is " + this.PidFile);
|
||||
try
|
||||
{
|
||||
File.WriteAllText(this.Pidfile, process.Id.ToString());
|
||||
File.WriteAllText(this.PidFile, process.Id.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("Cannot update the PID file " + this.Pidfile, ex);
|
||||
Logger.Error("Cannot update the PID file " + this.PidFile, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace WinSW.Plugins
|
|||
|
||||
object mappingNode = dict["mapping"];
|
||||
|
||||
if (!(mappingNode is List<object> mappings))
|
||||
if (mappingNode is not List<object> mappings)
|
||||
{
|
||||
throw new InvalidDataException("SharedDirectoryMapper mapping should be a list");
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace WinSW.Plugins
|
|||
|
||||
public static SharedDirectoryMapperConfig FromYaml(object yamlObject)
|
||||
{
|
||||
if (!(yamlObject is Dictionary<object, object> dict))
|
||||
if (yamlObject is not Dictionary<object, object> dict)
|
||||
{
|
||||
// TODO : throw ExtensionExeption
|
||||
throw new InvalidDataException("SharedDirectoryMapperConfig config error");
|
||||
|
@ -42,7 +42,7 @@ namespace WinSW.Plugins
|
|||
bool enableMapping = ConfigHelper.YamlBoolParse(enableMappingConfig);
|
||||
|
||||
string label = ExpandEnvironmentVariables((string)dict["label"]);
|
||||
string uncPath = ExpandEnvironmentVariables((string)dict["uncpath"]);
|
||||
string uncPath = ExpandEnvironmentVariables((string)dict["uncPath"]);
|
||||
|
||||
return new SharedDirectoryMapperConfig(enableMapping, label, uncPath);
|
||||
}
|
||||
|
|
|
@ -57,11 +57,11 @@ extensions:
|
|||
enabled: yes
|
||||
className: ""{this.testExtension}""
|
||||
settings:
|
||||
pidfile: 'foo/bar/pid.txt'
|
||||
stopTimeOut: 5000
|
||||
StopParentFirst: true";
|
||||
pidFile: 'foo/bar/pid.txt'
|
||||
stopTimeout: 5000
|
||||
stopParentFirst: true";
|
||||
|
||||
this._testServiceDescriptorYaml = YamlServiceConfigLoader.FromYaml(seedYaml).Config;
|
||||
this._testServiceDescriptorYaml = YamlServiceConfig.FromYaml(seedYaml);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -74,7 +74,7 @@ extensions:
|
|||
// Check the file is correct
|
||||
var extension = manager.Extensions["killRunawayProcess"] as RunawayProcessKillerExtension;
|
||||
Assert.IsNotNull(extension, "RunawayProcessKillerExtension should be loaded");
|
||||
Assert.AreEqual("foo/bar/pid.txt", extension.Pidfile, "Loaded PID file path is not equal to the expected one");
|
||||
Assert.AreEqual("foo/bar/pid.txt", extension.PidFile, "Loaded PID file path is not equal to the expected one");
|
||||
Assert.AreEqual(5000, extension.StopTimeout.TotalMilliseconds, "Loaded Stop Timeout is not equal to the expected one");
|
||||
Assert.AreEqual(true, extension.StopParentProcessFirst, "Loaded StopParentFirst is not equal to the expected one");
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ extensions:
|
|||
// Check the file is correct
|
||||
var extension = manager.Extensions["killRunawayProcess"] as RunawayProcessKillerExtension;
|
||||
Assert.IsNotNull(extension, "RunawayProcessKillerExtension should be loaded");
|
||||
Assert.AreEqual("foo/bar/pid.txt", extension.Pidfile, "Loaded PID file path is not equal to the expected one");
|
||||
Assert.AreEqual("foo/bar/pid.txt", extension.PidFile, "Loaded PID file path is not equal to the expected one");
|
||||
Assert.AreEqual(5000, extension.StopTimeout.TotalMilliseconds, "Loaded Stop Timeout is not equal to the expected one");
|
||||
Assert.AreEqual(true, extension.StopParentProcessFirst, "Loaded StopParentFirst is not equal to the expected one");
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ extensions:
|
|||
manager.LoadExtensions();
|
||||
var extension = manager.Extensions[extensionId] as RunawayProcessKillerExtension;
|
||||
Assert.IsNotNull(extension, "RunawayProcessKillerExtension should be loaded");
|
||||
Assert.AreEqual(pidfile, extension.Pidfile, "PidFile should have been retained during the config roundtrip");
|
||||
Assert.AreEqual(pidfile, extension.PidFile, "PidFile should have been retained during the config roundtrip");
|
||||
|
||||
// Inject PID
|
||||
File.WriteAllText(pidfile, proc.Id.ToString());
|
||||
|
|
|
@ -62,10 +62,10 @@ extensions:
|
|||
mapping:
|
||||
- enabled: false
|
||||
label: N
|
||||
uncpath: \\UNC
|
||||
uncPath: \\UNC
|
||||
- enabled: false
|
||||
label: M
|
||||
uncpath: \\UNC2
|
||||
uncPath: \\UNC2
|
||||
- id: mapNetworDirs2
|
||||
className: ""{this.testExtension}""
|
||||
enabled: true
|
||||
|
@ -73,12 +73,12 @@ extensions:
|
|||
mapping:
|
||||
- enabled: false
|
||||
label: X
|
||||
uncpath: \\UNC
|
||||
uncPath: \\UNC
|
||||
- enabled: false
|
||||
label: Y
|
||||
uncpath: \\UNC2";
|
||||
uncPath: \\UNC2";
|
||||
|
||||
this._testServiceDescriptorYaml = YamlServiceConfigLoader.FromYaml(seedYaml).Config;
|
||||
this._testServiceDescriptorYaml = YamlServiceConfig.FromYaml(seedYaml);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -102,28 +102,25 @@ $@"<service>
|
|||
[Test]
|
||||
public void VerifyWorkingDirectory()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this._extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.That(this._extendedServiceDescriptor.WorkingDirectory, Is.EqualTo(ExpectedWorkingDirectory));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyServiceLogonRight()
|
||||
{
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.AllowServiceAcountLogonRight, Is.True);
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.AllowServiceLogonRight, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyUsername()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.ServiceAccountUser, Is.EqualTo(Domain + "\\" + Username));
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.FullUser, Is.EqualTo(Domain + "\\" + Username));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyPassword()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.ServiceAccountPassword, Is.EqualTo(Password));
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.Password, Is.EqualTo(Password));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -307,7 +304,7 @@ $@"<service>
|
|||
+ "</serviceaccount>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = XmlServiceConfig.FromXML(seedXml);
|
||||
Assert.That(serviceDescriptor.ServiceAccount.AllowServiceAcountLogonRight, Is.False);
|
||||
Assert.That(serviceDescriptor.ServiceAccount.AllowServiceLogonRight, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -321,7 +318,7 @@ $@"<service>
|
|||
+ "</serviceaccount>"
|
||||
+ "</service>";
|
||||
var serviceDescriptor = XmlServiceConfig.FromXML(seedXml);
|
||||
Assert.That(serviceDescriptor.ServiceAccount.AllowServiceAcountLogonRight, Is.False);
|
||||
Assert.That(serviceDescriptor.ServiceAccount.AllowServiceLogonRight, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -30,14 +30,14 @@ arguments: My Arguments
|
|||
log:
|
||||
mode: roll
|
||||
logpath: c:\logs
|
||||
serviceaccount:
|
||||
serviceAccount:
|
||||
domain: {Domain}
|
||||
user: {Username}
|
||||
password: {Password}
|
||||
allowservicelogon: {AllowServiceAccountLogonRight}
|
||||
workingdirectory: {ExpectedWorkingDirectory}";
|
||||
allowServiceLogon: {AllowServiceAccountLogonRight}
|
||||
workingDirectory: {ExpectedWorkingDirectory}";
|
||||
|
||||
this._extendedServiceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
this._extendedServiceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -57,7 +57,7 @@ executable: node.exe
|
|||
arguments: My Arguments
|
||||
startMode: roll";
|
||||
|
||||
this._extendedServiceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
this._extendedServiceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
Assert.That(() => this._extendedServiceDescriptor.StartMode, Throws.ArgumentException);
|
||||
}
|
||||
|
||||
|
@ -72,61 +72,58 @@ executable: node.exe
|
|||
arguments: My Arguments
|
||||
startMode: manual";
|
||||
|
||||
this._extendedServiceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
this._extendedServiceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
Assert.That(this._extendedServiceDescriptor.StartMode, Is.EqualTo(ServiceStartMode.Manual));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyWorkingDirectory()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + this._extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.That(this._extendedServiceDescriptor.WorkingDirectory, Is.EqualTo(ExpectedWorkingDirectory));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyServiceLogonRight()
|
||||
{
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.AllowServiceAcountLogonRight, Is.True);
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.AllowServiceLogonRight, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyUsername()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.ServiceAccountUser, Is.EqualTo(Domain + "\\" + Username));
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.FullUser, Is.EqualTo(Domain + "\\" + Username));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyPassword()
|
||||
{
|
||||
Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory);
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.ServiceAccountPassword, Is.EqualTo(Password));
|
||||
Assert.That(_extendedServiceDescriptor.ServiceAccount.Password, Is.EqualTo(Password));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Priority()
|
||||
{
|
||||
var sd = YamlServiceConfigLoader.FromYaml(@"
|
||||
var sd = YamlServiceConfig.FromYaml(@"
|
||||
id: service.exe
|
||||
name: Service
|
||||
description: The Service.
|
||||
executable: node.exe
|
||||
priority: normal").Config;
|
||||
priority: normal");
|
||||
Assert.That(sd.Priority, Is.EqualTo(ProcessPriorityClass.Normal));
|
||||
|
||||
sd = YamlServiceConfigLoader.FromYaml(@"
|
||||
sd = YamlServiceConfig.FromYaml(@"
|
||||
id: service.exe
|
||||
name: Service
|
||||
description: The Service.
|
||||
executable: node.exe
|
||||
priority: idle").Config;
|
||||
priority: idle");
|
||||
Assert.That(sd.Priority, Is.EqualTo(ProcessPriorityClass.Idle));
|
||||
|
||||
sd = YamlServiceConfigLoader.FromYaml(@"
|
||||
sd = YamlServiceConfig.FromYaml(@"
|
||||
id: service.exe
|
||||
name: Service
|
||||
description: The Service.
|
||||
executable: node.exe").Config;
|
||||
executable: node.exe");
|
||||
Assert.That(sd.Priority, Is.EqualTo(ProcessPriorityClass.Normal));
|
||||
}
|
||||
|
||||
|
@ -145,7 +142,7 @@ name: Service
|
|||
description: The Service.
|
||||
executable: node.exe
|
||||
stopParentProcessFirst: false";
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.StopParentProcessFirst, Is.False);
|
||||
}
|
||||
|
@ -159,7 +156,7 @@ description: The Service.
|
|||
executable: node.exe
|
||||
stopTimeout: 60sec";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.StopTimeout, Is.EqualTo(TimeSpan.FromSeconds(60)));
|
||||
}
|
||||
|
@ -174,7 +171,7 @@ description: The Service.
|
|||
executable: node.exe
|
||||
stopTimeout: 10min";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.StopTimeout, Is.EqualTo(TimeSpan.FromMinutes(10)));
|
||||
}
|
||||
|
@ -190,7 +187,7 @@ executable: node.exe
|
|||
log:
|
||||
name: MyTestApp";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.Log.Name, Is.EqualTo("MyTestApp"));
|
||||
}
|
||||
|
@ -206,7 +203,7 @@ executable: node.exe
|
|||
log:
|
||||
outFileDisabled: true";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.Log.OutFileDisabled, Is.True);
|
||||
}
|
||||
|
@ -222,7 +219,7 @@ executable: node.exe
|
|||
log:
|
||||
errFileDisabled: true";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.Log.ErrFileDisabled, Is.True);
|
||||
}
|
||||
|
@ -238,7 +235,7 @@ executable: node.exe
|
|||
log:
|
||||
outFilePattern: .out.test.log";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.Log.OutFilePattern, Is.EqualTo(".out.test.log"));
|
||||
}
|
||||
|
@ -254,7 +251,7 @@ executable: node.exe
|
|||
log:
|
||||
errFilePattern: .err.test.log";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.Log.ErrFilePattern, Is.EqualTo(".err.test.log"));
|
||||
}
|
||||
|
@ -273,7 +270,7 @@ log:
|
|||
sizeThreshold: 112
|
||||
keepFiles: 113";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
serviceDescriptor.BaseName = "service";
|
||||
|
||||
|
@ -297,7 +294,7 @@ log:
|
|||
period: 7
|
||||
pattern: log pattern";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
serviceDescriptor.BaseName = "service";
|
||||
|
||||
|
@ -322,7 +319,7 @@ log:
|
|||
pattern: yyyy-MM-dd
|
||||
autoRollAtTime: 00:00:00";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
serviceDescriptor.BaseName = "service";
|
||||
|
||||
|
@ -341,15 +338,15 @@ id: service.exe
|
|||
name: Service
|
||||
description: The Service.
|
||||
executable: node.exe
|
||||
serviceaccount:
|
||||
serviceAccount:
|
||||
domain: {Domain}
|
||||
user: {Username}
|
||||
password: {Password}
|
||||
allowservicelogon: false";
|
||||
allowServiceLogon: false";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.ServiceAccount.AllowServiceAcountLogonRight, Is.False);
|
||||
Assert.That(serviceDescriptor.ServiceAccount.AllowServiceLogonRight, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -360,44 +357,14 @@ id: service.exe
|
|||
name: Service
|
||||
description: The Service.
|
||||
executable: node.exe
|
||||
serviceaccount:
|
||||
serviceAccount:
|
||||
domain: {Domain}
|
||||
user: {Username}
|
||||
password: {Password}";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.ServiceAccount.AllowServiceAcountLogonRight, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyWaitHint()
|
||||
{
|
||||
string yaml = $@"
|
||||
id: service.exe
|
||||
name: Service
|
||||
description: The Service.
|
||||
executable: node.exe
|
||||
waitHint: 20 min";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
|
||||
Assert.That(serviceDescriptor.WaitHint, Is.EqualTo(TimeSpan.FromMinutes(20)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifySleepTime()
|
||||
{
|
||||
string yaml = $@"
|
||||
id: service.exe
|
||||
name: Service
|
||||
description: The Service.
|
||||
executable: node.exe
|
||||
sleepTime: 3 hrs";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
|
||||
Assert.That(serviceDescriptor.SleepTime, Is.EqualTo(TimeSpan.FromHours(3)));
|
||||
Assert.That(serviceDescriptor.ServiceAccount.AllowServiceLogonRight, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -408,9 +375,9 @@ id: service.exe
|
|||
name: Service
|
||||
description: The Service.
|
||||
executable: node.exe
|
||||
resetFailureAfter: 75 sec";
|
||||
resetFailure: 75 sec";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.ResetFailureAfter, Is.EqualTo(TimeSpan.FromSeconds(75)));
|
||||
}
|
||||
|
@ -425,7 +392,7 @@ description: The Service.
|
|||
executable: node.exe
|
||||
stopTimeout: 35 sec";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.StopTimeout, Is.EqualTo(TimeSpan.FromSeconds(35)));
|
||||
}
|
||||
|
@ -440,7 +407,7 @@ description: The Service.
|
|||
executable: node.exe
|
||||
arguments: arg";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.Arguments, Is.EqualTo("arg"));
|
||||
}
|
||||
|
@ -454,7 +421,7 @@ description: The Service.
|
|||
executable: node.exe
|
||||
delayedAutoStart: true";
|
||||
|
||||
var serviceDescriptor = YamlServiceConfigLoader.FromYaml(yaml).Config;
|
||||
var serviceDescriptor = YamlServiceConfig.FromYaml(yaml);
|
||||
|
||||
Assert.That(serviceDescriptor.DelayedAutoStart, Is.EqualTo(true));
|
||||
}
|
||||
|
@ -470,7 +437,7 @@ description: This is test winsw";
|
|||
|
||||
Assert.That(() =>
|
||||
{
|
||||
_ = YamlServiceConfigLoader.FromYaml(yml).Config.Name;
|
||||
_ = YamlServiceConfig.FromYaml(yml).Name;
|
||||
}, Throws.TypeOf<InvalidOperationException>());
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ namespace winswTests.Util
|
|||
string fullyQualifiedExtensionName = ExtensionTestBase.GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension));
|
||||
var str = new StringBuilder();
|
||||
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(" <stopParentFirst>{0}</stopParentFirst>\n", ext.StopParentProcessFirst);
|
||||
str.AppendFormat(" <checkWinSWEnvironmentVariable>{0}</checkWinSWEnvironmentVariable>\n", ext.CheckWinSWEnvironmentVariable);
|
||||
|
|
|
@ -272,15 +272,15 @@ namespace WinSW
|
|||
{
|
||||
if (config.ServiceAccount.HasServiceAccount())
|
||||
{
|
||||
username = config.ServiceAccount.ServiceAccountUser;
|
||||
password = config.ServiceAccount.ServiceAccountPassword;
|
||||
allowServiceLogonRight = config.ServiceAccount.AllowServiceAcountLogonRight;
|
||||
username = config.ServiceAccount.FullUser;
|
||||
password = config.ServiceAccount.Password;
|
||||
allowServiceLogonRight = config.ServiceAccount.AllowServiceLogonRight;
|
||||
}
|
||||
}
|
||||
|
||||
if (allowServiceLogonRight)
|
||||
{
|
||||
Security.AddServiceLogonRight(config.ServiceAccount.ServiceAccountDomain!, config.ServiceAccount.ServiceAccountName!);
|
||||
Security.AddServiceLogonRight(config.ServiceAccount.Domain!, config.ServiceAccount.User!);
|
||||
}
|
||||
|
||||
using var sc = scm.CreateService(
|
||||
|
@ -704,7 +704,7 @@ namespace WinSW
|
|||
|
||||
IServiceConfig config =
|
||||
File.Exists(Path.Combine(directory, baseName + ".xml")) ? new XmlServiceConfig(baseName, directory) :
|
||||
File.Exists(Path.Combine(directory, baseName + ".yml")) ? new YamlServiceConfigLoader(baseName, directory).Config :
|
||||
File.Exists(Path.Combine(directory, baseName + ".yml")) ? new YamlServiceConfig(baseName, directory) :
|
||||
throw new FileNotFoundException($"Unable to locate {baseName}.[xml|yml] file within executable directory");
|
||||
|
||||
// .wrapper.log
|
||||
|
|
Loading…
Reference in New Issue