mirror of https://github.com/winsw/winsw
Decouple Default Settings to a separate publicly accessible class.
Required for tests.pull/170/head
parent
413e24ebeb
commit
14f32cd309
|
@ -0,0 +1,71 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using WMI;
|
||||||
|
|
||||||
|
namespace winsw.Configuration
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default WinSW settings
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DefaultWinSWSettings : IWinSWConfiguration
|
||||||
|
{
|
||||||
|
public string Id { get { return null; } }
|
||||||
|
public string Caption { get { return null; } }
|
||||||
|
public string Description { get { return null; } }
|
||||||
|
public string Executable { get { return null; } }
|
||||||
|
|
||||||
|
public string ExecutablePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// this returns the executable name as given by the calling process, so
|
||||||
|
// it needs to be absolutized.
|
||||||
|
string p = Environment.GetCommandLineArgs()[0];
|
||||||
|
return Path.GetFullPath(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Installation
|
||||||
|
public bool AllowServiceAcountLogonRight { get { return false; } }
|
||||||
|
public string ServiceAccountPassword { get { return null; } }
|
||||||
|
public string ServiceAccountUser { get { return null; } }
|
||||||
|
public List<winsw.Native.SC_ACTION> FailureActions { get { return new List<winsw.Native.SC_ACTION>(); } }
|
||||||
|
public TimeSpan ResetFailureAfter { get { return TimeSpan.FromDays(1); } }
|
||||||
|
|
||||||
|
// Executable management
|
||||||
|
public string Arguments { get { return ""; } }
|
||||||
|
public string Startarguments { get { return null; } }
|
||||||
|
public string StopExecutable { get { return null; } }
|
||||||
|
public string Stoparguments { get { return null; } }
|
||||||
|
public string WorkingDirectory { get { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } }
|
||||||
|
public ProcessPriorityClass Priority { get { return ProcessPriorityClass.Normal; } }
|
||||||
|
public TimeSpan StopTimeout { get { return TimeSpan.FromSeconds(15); } }
|
||||||
|
public bool StopParentProcessFirst { get { return false; } }
|
||||||
|
|
||||||
|
// Service management
|
||||||
|
public StartMode StartMode { get { return StartMode.Automatic; } }
|
||||||
|
public string[] ServiceDependencies { get { return new string[0]; } }
|
||||||
|
public TimeSpan WaitHint { get { return TimeSpan.FromSeconds(15); } }
|
||||||
|
public TimeSpan SleepTime { get { return TimeSpan.FromSeconds(1); } }
|
||||||
|
public bool Interactive { get { return false; } }
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
public string LogDirectory { get { return Path.GetDirectoryName(ExecutablePath); } }
|
||||||
|
public string LogMode { get { return "append"; } }
|
||||||
|
|
||||||
|
// Environment
|
||||||
|
public List<Download> Downloads { get { return new List<Download>(); } }
|
||||||
|
public Dictionary<string, string> EnvironmentVariables { get { return new Dictionary<string, string>(); } }
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
public bool BeepOnShutdown { get { return false; } }
|
||||||
|
|
||||||
|
// Extensions
|
||||||
|
public XmlNode ExtensionsConfiguration { get {return null; } }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Xml;
|
||||||
|
using WMI;
|
||||||
|
namespace winsw.Configuration
|
||||||
|
{
|
||||||
|
interface IWinSWConfiguration
|
||||||
|
{
|
||||||
|
//TODO: Document the parameters && refactor
|
||||||
|
|
||||||
|
string Id { get; }
|
||||||
|
string Caption { get; }
|
||||||
|
string Description { get; }
|
||||||
|
string Executable { get; }
|
||||||
|
string ExecutablePath { get; }
|
||||||
|
|
||||||
|
// Installation
|
||||||
|
bool AllowServiceAcountLogonRight { get; }
|
||||||
|
string ServiceAccountPassword { get; }
|
||||||
|
string ServiceAccountUser { get; }
|
||||||
|
List<winsw.Native.SC_ACTION> FailureActions { get; }
|
||||||
|
TimeSpan ResetFailureAfter { get; }
|
||||||
|
|
||||||
|
// Executable management
|
||||||
|
string Arguments { get; }
|
||||||
|
string Startarguments { get; }
|
||||||
|
string StopExecutable { get; }
|
||||||
|
string Stoparguments { get; }
|
||||||
|
string WorkingDirectory { get; }
|
||||||
|
ProcessPriorityClass Priority { get; }
|
||||||
|
TimeSpan StopTimeout { get; }
|
||||||
|
bool StopParentProcessFirst { get; }
|
||||||
|
|
||||||
|
// Service management
|
||||||
|
StartMode StartMode { get; }
|
||||||
|
string[] ServiceDependencies { get; }
|
||||||
|
TimeSpan WaitHint { get; }
|
||||||
|
TimeSpan SleepTime { get; }
|
||||||
|
bool Interactive { get; }
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
string LogDirectory { get; }
|
||||||
|
//TODO: replace by enum
|
||||||
|
string LogMode { get; }
|
||||||
|
|
||||||
|
// Environment
|
||||||
|
List<Download> Downloads { get; }
|
||||||
|
Dictionary<string, string> EnvironmentVariables { get; }
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
bool BeepOnShutdown { get; }
|
||||||
|
|
||||||
|
// Extensions
|
||||||
|
XmlNode ExtensionsConfiguration { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using winsw.Configuration;
|
||||||
using winsw.Native;
|
using winsw.Native;
|
||||||
using winsw.Util;
|
using winsw.Util;
|
||||||
using WMI;
|
using WMI;
|
||||||
|
@ -14,17 +15,21 @@ namespace winsw
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// In-memory representation of the configuration file.
|
/// In-memory representation of the configuration file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ServiceDescriptor
|
public class ServiceDescriptor : IWinSWConfiguration
|
||||||
{
|
{
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
protected readonly XmlDocument dom = new XmlDocument();
|
protected readonly XmlDocument dom = new XmlDocument();
|
||||||
|
|
||||||
|
private static readonly DefaultWinSWSettings defaults = new DefaultWinSWSettings();
|
||||||
|
public static DefaultWinSWSettings Defaults { get { return defaults; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Where did we find the configuration file?
|
/// Where did we find the configuration file?
|
||||||
///
|
///
|
||||||
/// This string is "c:\abc\def\ghi" when the configuration XML is "c:\abc\def\ghi.xml"
|
/// This string is "c:\abc\def\ghi" when the configuration XML is "c:\abc\def\ghi.xml"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string BasePath { get; set; }
|
public string BasePath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The file name portion of the configuration file.
|
/// The file name portion of the configuration file.
|
||||||
///
|
///
|
||||||
|
@ -36,10 +41,8 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// this returns the executable name as given by the calling process, so
|
// Currently there is no opportunity to alter the executable path
|
||||||
// it needs to be absolutized.
|
return Defaults.ExecutablePath;
|
||||||
string p = Environment.GetCommandLineArgs()[0];
|
|
||||||
return Path.GetFullPath(p);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +194,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
string arguments = AppendTags("argument");
|
string arguments = AppendTags("argument", Defaults.Arguments);
|
||||||
|
|
||||||
if (arguments == null)
|
if (arguments == null)
|
||||||
{
|
{
|
||||||
|
@ -199,7 +202,7 @@ namespace winsw
|
||||||
|
|
||||||
if (argumentsNode == null)
|
if (argumentsNode == null)
|
||||||
{
|
{
|
||||||
return "";
|
return Defaults.Arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Environment.ExpandEnvironmentVariables(argumentsNode.InnerText);
|
return Environment.ExpandEnvironmentVariables(argumentsNode.InnerText);
|
||||||
|
@ -218,7 +221,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return AppendTags("startargument");
|
return AppendTags("startargument", Defaults.Startarguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +232,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return AppendTags("stopargument");
|
return AppendTags("stopargument", Defaults.Startarguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +240,7 @@ namespace winsw
|
||||||
public string WorkingDirectory {
|
public string WorkingDirectory {
|
||||||
get {
|
get {
|
||||||
var wd = SingleElement("workingdirectory", true);
|
var wd = SingleElement("workingdirectory", true);
|
||||||
return String.IsNullOrEmpty(wd) ? Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) : wd;
|
return String.IsNullOrEmpty(wd) ? Defaults.WorkingDirectory : wd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,13 +279,13 @@ namespace winsw
|
||||||
/// Combines the contents of all the elements of the given name,
|
/// Combines the contents of all the elements of the given name,
|
||||||
/// or return null if no element exists. Handles whitespace quotation.
|
/// or return null if no element exists. Handles whitespace quotation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string AppendTags(string tagName)
|
private string AppendTags(string tagName, string defaultValue = null)
|
||||||
{
|
{
|
||||||
XmlNode argumentNode = dom.SelectSingleNode("//" + tagName);
|
XmlNode argumentNode = dom.SelectSingleNode("//" + tagName);
|
||||||
|
|
||||||
if (argumentNode == null)
|
if (argumentNode == null)
|
||||||
{
|
{
|
||||||
return null;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -327,31 +330,51 @@ namespace winsw
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Path.GetDirectoryName(ExecutablePath);
|
return Defaults.LogDirectory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string LogMode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string mode = null;
|
||||||
|
|
||||||
|
// first, backward compatibility with older configuration
|
||||||
|
XmlElement e = (XmlElement)dom.SelectSingleNode("//logmode");
|
||||||
|
if (e != null)
|
||||||
|
{
|
||||||
|
mode = e.InnerText;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// this is more modern way, to support nested elements as configuration
|
||||||
|
e = (XmlElement)dom.SelectSingleNode("//log");
|
||||||
|
if (e != null)
|
||||||
|
mode = e.GetAttribute("mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == null)
|
||||||
|
{
|
||||||
|
mode = Defaults.LogMode;
|
||||||
|
}
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public LogHandler LogHandler
|
public LogHandler LogHandler
|
||||||
{
|
{
|
||||||
|
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
string mode=null;
|
|
||||||
|
|
||||||
// first, backward compatibility with older configuration
|
|
||||||
XmlElement e = (XmlElement)dom.SelectSingleNode("//logmode");
|
XmlElement e = (XmlElement)dom.SelectSingleNode("//logmode");
|
||||||
if (e!=null) {
|
if (e == null)
|
||||||
mode = e.InnerText;
|
{
|
||||||
} else {
|
|
||||||
// this is more modern way, to support nested elements as configuration
|
// this is more modern way, to support nested elements as configuration
|
||||||
e = (XmlElement)dom.SelectSingleNode("//log");
|
e = (XmlElement)dom.SelectSingleNode("//log");
|
||||||
if (e!=null)
|
|
||||||
mode = e.GetAttribute("mode");
|
|
||||||
}
|
}
|
||||||
|
switch (LogMode)
|
||||||
if (mode == null) mode = "append";
|
|
||||||
|
|
||||||
switch (mode)
|
|
||||||
{
|
{
|
||||||
case "rotate":
|
case "rotate":
|
||||||
return new SizeBasedRollingLogAppender(LogDirectory, BaseName);
|
return new SizeBasedRollingLogAppender(LogDirectory, BaseName);
|
||||||
|
@ -384,7 +407,7 @@ namespace winsw
|
||||||
return new DefaultLogAppender(LogDirectory, BaseName);
|
return new DefaultLogAppender(LogDirectory, BaseName);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidDataException("Undefined logging mode: " + mode);
|
throw new InvalidDataException("Undefined logging mode: " + LogMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,17 +420,18 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
ArrayList serviceDependencies = new ArrayList();
|
|
||||||
|
|
||||||
var xmlNodeList = dom.SelectNodes("//depend");
|
var xmlNodeList = dom.SelectNodes("//depend");
|
||||||
if (xmlNodeList != null)
|
if (xmlNodeList != null)
|
||||||
|
{
|
||||||
|
ArrayList serviceDependencies = new ArrayList();
|
||||||
foreach (XmlNode depend in xmlNodeList)
|
foreach (XmlNode depend in xmlNodeList)
|
||||||
{
|
{
|
||||||
serviceDependencies.Add(depend.InnerText);
|
serviceDependencies.Add(depend.InnerText);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (string[])serviceDependencies.ToArray(typeof(string));
|
return (string[])serviceDependencies.ToArray(typeof(string));
|
||||||
}
|
}
|
||||||
|
return Defaults.ServiceDependencies;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Id
|
public string Id
|
||||||
|
@ -442,7 +466,7 @@ namespace winsw
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var p = SingleElement("startmode", true);
|
var p = SingleElement("startmode", true);
|
||||||
if (p == null) return StartMode.Automatic; // default value
|
if (p == null) return Defaults.StartMode;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return (StartMode)Enum.Parse(typeof(StartMode), p, true);
|
return (StartMode)Enum.Parse(typeof(StartMode), p, true);
|
||||||
|
@ -460,7 +484,7 @@ namespace winsw
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the service should when finished on shutdown.
|
/// True if the service should beep when finished on shutdown.
|
||||||
/// This doesn't work on some OSes. See http://msdn.microsoft.com/en-us/library/ms679277%28VS.85%29.aspx
|
/// This doesn't work on some OSes. See http://msdn.microsoft.com/en-us/library/ms679277%28VS.85%29.aspx
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool BeepOnShutdown
|
public bool BeepOnShutdown
|
||||||
|
@ -481,7 +505,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return SingleTimeSpanElement(dom.FirstChild, "waithint", TimeSpan.FromSeconds(15));
|
return SingleTimeSpanElement(dom.FirstChild, "waithint", Defaults.WaitHint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,7 +519,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return SingleTimeSpanElement(dom.FirstChild, "sleeptime", TimeSpan.FromSeconds(1));
|
return SingleTimeSpanElement(dom.FirstChild, "sleeptime", Defaults.SleepTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,9 +562,13 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
List<Download> r = new List<Download>();
|
|
||||||
var xmlNodeList = dom.SelectNodes("//download");
|
var xmlNodeList = dom.SelectNodes("//download");
|
||||||
if (xmlNodeList != null)
|
if (xmlNodeList == null)
|
||||||
|
{
|
||||||
|
return Defaults.Downloads;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Download> r = new List<Download>();
|
||||||
foreach (XmlNode n in xmlNodeList)
|
foreach (XmlNode n in xmlNodeList)
|
||||||
{
|
{
|
||||||
r.Add(new Download(n));
|
r.Add(new Download(n));
|
||||||
|
@ -587,7 +615,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return SingleTimeSpanElement(dom.FirstChild, "resetfailure", TimeSpan.FromDays(1));
|
return SingleTimeSpanElement(dom.FirstChild, "resetfailure", Defaults.ResetFailureAfter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,13 +697,13 @@ namespace winsw
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Time to wait for the service to gracefully shutdown before we forcibly kill it
|
/// Time to wait for the service to gracefully shutdown the executable before we forcibly kill it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeSpan StopTimeout
|
public TimeSpan StopTimeout
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return SingleTimeSpanElement(dom.FirstChild, "stoptimeout", TimeSpan.FromSeconds(15));
|
return SingleTimeSpanElement(dom.FirstChild, "stoptimeout", Defaults.StopTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,7 +717,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return false;
|
return Defaults.StopParentProcessFirst;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,7 +729,7 @@ namespace winsw
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var p = SingleElement("priority",true);
|
var p = SingleElement("priority",true);
|
||||||
if (p == null) return ProcessPriorityClass.Normal; // default value
|
if (p == null) return Defaults.Priority;
|
||||||
|
|
||||||
return (ProcessPriorityClass)Enum.Parse(typeof(ProcessPriorityClass), p, true);
|
return (ProcessPriorityClass)Enum.Parse(typeof(ProcessPriorityClass), p, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Configuration\DefaultSettings.cs" />
|
||||||
<Compile Include="Download.cs" />
|
<Compile Include="Download.cs" />
|
||||||
<Compile Include="DynamicProxy.cs" />
|
<Compile Include="DynamicProxy.cs" />
|
||||||
<Compile Include="Extensions\AbstractWinSWExtension.cs" />
|
<Compile Include="Extensions\AbstractWinSWExtension.cs" />
|
||||||
|
@ -53,6 +54,7 @@
|
||||||
<Compile Include="Extensions\IWinSWExtension.cs" />
|
<Compile Include="Extensions\IWinSWExtension.cs" />
|
||||||
<Compile Include="Extensions\WinSWExtensionDescriptor.cs" />
|
<Compile Include="Extensions\WinSWExtensionDescriptor.cs" />
|
||||||
<Compile Include="Extensions\WinSWExtensionManager.cs" />
|
<Compile Include="Extensions\WinSWExtensionManager.cs" />
|
||||||
|
<Compile Include="Configuration\IWinSWConfiguration.cs" />
|
||||||
<Compile Include="LogAppenders.cs" />
|
<Compile Include="LogAppenders.cs" />
|
||||||
<Compile Include="Logging\ServiceEventLogAppender.cs" />
|
<Compile Include="Logging\ServiceEventLogAppender.cs" />
|
||||||
<Compile Include="Logging\IServiceEventLogProvider.cs" />
|
<Compile Include="Logging\IServiceEventLogProvider.cs" />
|
||||||
|
|
Loading…
Reference in New Issue