mirror of https://github.com/winsw/winsw
Splitting a file into smaller chunks.
parent
6060b4a58d
commit
8d1deb2ae4
|
@ -0,0 +1,58 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.ServiceProcess;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using WMI;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace winsw
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specify the download activities prior to the launch.
|
||||||
|
/// This enables self-updating services.
|
||||||
|
/// </summary>
|
||||||
|
public class Download
|
||||||
|
{
|
||||||
|
public readonly string From;
|
||||||
|
public readonly string To;
|
||||||
|
|
||||||
|
internal Download(XmlNode n)
|
||||||
|
{
|
||||||
|
From = Environment.ExpandEnvironmentVariables(n.Attributes["from"].Value);
|
||||||
|
To = Environment.ExpandEnvironmentVariables(n.Attributes["to"].Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Perform()
|
||||||
|
{
|
||||||
|
WebRequest req = WebRequest.Create(From);
|
||||||
|
WebResponse rsp = req.GetResponse();
|
||||||
|
FileStream tmpstream = new FileStream(To + ".tmp", FileMode.Create);
|
||||||
|
CopyStream(rsp.GetResponseStream(), tmpstream);
|
||||||
|
// only after we successfully downloaded a file, overwrite the existing one
|
||||||
|
if (File.Exists(To))
|
||||||
|
File.Delete(To);
|
||||||
|
File.Move(To + ".tmp", To);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CopyStream(Stream i, Stream o)
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int len = i.Read(buf, 0, buf.Length);
|
||||||
|
if (len <= 0) break;
|
||||||
|
o.Write(buf, 0, len);
|
||||||
|
}
|
||||||
|
i.Close();
|
||||||
|
o.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
396
Main.cs
396
Main.cs
|
@ -37,402 +37,6 @@ namespace winsw
|
||||||
SERVICE_PAUSED = 0x00000007,
|
SERVICE_PAUSED = 0x00000007,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// In-memory representation of the configuration file.
|
|
||||||
/// </summary>
|
|
||||||
public class ServiceDescriptor
|
|
||||||
{
|
|
||||||
private readonly XmlDocument dom = new XmlDocument();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Where did we find the configuration file?
|
|
||||||
///
|
|
||||||
/// This string is "c:\abc\def\ghi" when the configuration XML is "c:\abc\def\ghi.xml"
|
|
||||||
/// </summary>
|
|
||||||
public readonly string BasePath;
|
|
||||||
/// <summary>
|
|
||||||
/// The file name portion of the configuration file.
|
|
||||||
///
|
|
||||||
/// In the above example, this would be "ghi".
|
|
||||||
/// </summary>
|
|
||||||
public readonly string BaseName;
|
|
||||||
|
|
||||||
public static 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.Combine(AppDomain.CurrentDomain.BaseDirectory, p);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServiceDescriptor()
|
|
||||||
{
|
|
||||||
// find co-located configuration xml. We search up to the ancestor directories to simplify debugging,
|
|
||||||
// as well as trimming off ".vshost" suffix (which is used during debugging)
|
|
||||||
string p = ExecutablePath;
|
|
||||||
string baseName = Path.GetFileNameWithoutExtension(p);
|
|
||||||
if (baseName.EndsWith(".vshost")) baseName = baseName.Substring(0, baseName.Length - 7);
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
p = Path.GetDirectoryName(p);
|
|
||||||
if (File.Exists(Path.Combine(p, baseName + ".xml")))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// register the base directory as environment variable so that future expansions can refer to this.
|
|
||||||
Environment.SetEnvironmentVariable("BASE", p);
|
|
||||||
|
|
||||||
BaseName = baseName;
|
|
||||||
BasePath = Path.Combine(p, BaseName);
|
|
||||||
|
|
||||||
dom.Load(BasePath+".xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
private string SingleElement(string tagName)
|
|
||||||
{
|
|
||||||
var n = dom.SelectSingleNode("//" + tagName);
|
|
||||||
if (n == null) throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
|
|
||||||
return Environment.ExpandEnvironmentVariables(n.InnerText);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Path to the executable.
|
|
||||||
/// </summary>
|
|
||||||
public string Executable
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return SingleElement("executable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optionally specify a different Path to an executable to shutdown the service.
|
|
||||||
/// </summary>
|
|
||||||
public string StopExecutable
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return AppendTags("stopexecutable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Arguments or multiple optional argument elements which overrule the arguments element.
|
|
||||||
/// </summary>
|
|
||||||
public string Arguments
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
string arguments = AppendTags("argument");
|
|
||||||
|
|
||||||
if (arguments == null)
|
|
||||||
{
|
|
||||||
var tagName = "arguments";
|
|
||||||
var argumentsNode = dom.SelectSingleNode("//" + tagName);
|
|
||||||
|
|
||||||
if (argumentsNode == null)
|
|
||||||
{
|
|
||||||
if (AppendTags("startargument") == null)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Environment.ExpandEnvironmentVariables(argumentsNode.InnerText);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return arguments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Multiple optional startargument elements.
|
|
||||||
/// </summary>
|
|
||||||
public string Startarguments
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return AppendTags("startargument");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Multiple optional stopargument elements.
|
|
||||||
/// </summary>
|
|
||||||
public string Stoparguments
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return AppendTags("stopargument");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Combines the contents of all the elements of the given name,
|
|
||||||
/// or return null if no element exists.
|
|
||||||
/// </summary>
|
|
||||||
private string AppendTags(string tagName)
|
|
||||||
{
|
|
||||||
XmlNode argumentNode = dom.SelectSingleNode("//" + tagName);
|
|
||||||
|
|
||||||
if (argumentNode == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string arguments = "";
|
|
||||||
|
|
||||||
foreach (XmlNode argument in dom.SelectNodes("//" + tagName))
|
|
||||||
{
|
|
||||||
arguments += " " + argument.InnerText;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Environment.ExpandEnvironmentVariables(arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// LogDirectory is the service wrapper executable directory or the optionally specified logpath element.
|
|
||||||
/// </summary>
|
|
||||||
public string LogDirectory
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
XmlNode loggingNode = dom.SelectSingleNode("//logpath");
|
|
||||||
|
|
||||||
if (loggingNode != null)
|
|
||||||
{
|
|
||||||
return loggingNode.InnerText;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Path.GetDirectoryName(ExecutablePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Logmode to 'reset', 'rotate' once or 'append' [default] the out.log and err.log files.
|
|
||||||
/// </summary>
|
|
||||||
public string Logmode
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
XmlNode logmodeNode = dom.SelectSingleNode("//logmode");
|
|
||||||
|
|
||||||
if (logmodeNode == null)
|
|
||||||
{
|
|
||||||
return "append";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return logmodeNode.InnerText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optionally specified depend services that must start before this service starts.
|
|
||||||
/// </summary>
|
|
||||||
public string[] ServiceDependencies
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
System.Collections.ArrayList serviceDependencies = new System.Collections.ArrayList();
|
|
||||||
|
|
||||||
foreach (XmlNode depend in dom.SelectNodes("//depend"))
|
|
||||||
{
|
|
||||||
serviceDependencies.Add(depend.InnerText);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (string[])serviceDependencies.ToArray(typeof(string));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Id
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return SingleElement("id");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Caption
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return SingleElement("name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Description
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return SingleElement("description");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if the service should when finished on shutdown.
|
|
||||||
/// </summary>
|
|
||||||
public bool BeepOnShutdown
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return dom.SelectSingleNode("//beeponshutdown") != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The estimated time required for a pending stop operation, in milliseconds (default 15 secs).
|
|
||||||
/// Before the specified amount of time has elapsed, the service should make its next call to the SetServiceStatus function
|
|
||||||
/// with either an incremented checkPoint value or a change in currentState. (see http://msdn.microsoft.com/en-us/library/ms685996.aspx)
|
|
||||||
/// </summary>
|
|
||||||
public int WaitHint
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
XmlNode waithintNode = dom.SelectSingleNode("//waithint");
|
|
||||||
|
|
||||||
if (waithintNode == null)
|
|
||||||
{
|
|
||||||
return 15000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return int.Parse(waithintNode.InnerText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The time, in milliseconds (default 1 sec), before the service should make its next call to the SetServiceStatus function
|
|
||||||
/// with an incremented checkPoint value.
|
|
||||||
/// Do not wait longer than the wait hint. A good interval is one-tenth of the wait hint but not less than 1 second and not more than 10 seconds.
|
|
||||||
/// </summary>
|
|
||||||
public int SleepTime
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
XmlNode sleeptimeNode = dom.SelectSingleNode("//sleeptime");
|
|
||||||
|
|
||||||
if (sleeptimeNode == null)
|
|
||||||
{
|
|
||||||
return 1000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return int.Parse(sleeptimeNode.InnerText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if the service can interact with the desktop.
|
|
||||||
/// </summary>
|
|
||||||
public bool Interactive
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return dom.SelectSingleNode("//interactive") != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Environment variable overrides
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary<string, string> EnvironmentVariables
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Dictionary<string, string> map = new Dictionary<string, string>();
|
|
||||||
foreach (XmlNode n in dom.SelectNodes("//env"))
|
|
||||||
{
|
|
||||||
string key = n.Attributes["name"].Value;
|
|
||||||
string value = Environment.ExpandEnvironmentVariables(n.Attributes["value"].Value);
|
|
||||||
map[key] = value;
|
|
||||||
|
|
||||||
Environment.SetEnvironmentVariable(key, value);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List of downloads to be performed by the wrapper before starting
|
|
||||||
/// a service.
|
|
||||||
/// </summary>
|
|
||||||
public List<Download> Downloads
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
List<Download> r = new List<Download>();
|
|
||||||
foreach (XmlNode n in dom.SelectNodes("//download"))
|
|
||||||
{
|
|
||||||
r.Add(new Download(n));
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Specify the download activities prior to the launch.
|
|
||||||
/// This enables self-updating services.
|
|
||||||
/// </summary>
|
|
||||||
public class Download
|
|
||||||
{
|
|
||||||
public readonly string From;
|
|
||||||
public readonly string To;
|
|
||||||
|
|
||||||
internal Download(XmlNode n)
|
|
||||||
{
|
|
||||||
From = Environment.ExpandEnvironmentVariables(n.Attributes["from"].Value);
|
|
||||||
To = Environment.ExpandEnvironmentVariables(n.Attributes["to"].Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Perform()
|
|
||||||
{
|
|
||||||
WebRequest req = WebRequest.Create(From);
|
|
||||||
WebResponse rsp = req.GetResponse();
|
|
||||||
FileStream tmpstream = new FileStream(To+".tmp", FileMode.Create);
|
|
||||||
CopyStream(rsp.GetResponseStream(), tmpstream);
|
|
||||||
// only after we successfully downloaded a file, overwrite the existing one
|
|
||||||
if(File.Exists(To))
|
|
||||||
File.Delete(To);
|
|
||||||
File.Move(To + ".tmp", To);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CopyStream(Stream i, Stream o)
|
|
||||||
{
|
|
||||||
byte[] buf = new byte[8192];
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
int len = i.Read(buf, 0, buf.Length);
|
|
||||||
if (len <= 0) break;
|
|
||||||
o.Write(buf, 0, len);
|
|
||||||
}
|
|
||||||
i.Close();
|
|
||||||
o.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class WrapperService : ServiceBase
|
public class WrapperService : ServiceBase
|
||||||
{
|
{
|
||||||
[DllImport("ADVAPI32.DLL")]
|
[DllImport("ADVAPI32.DLL")]
|
||||||
|
|
|
@ -0,0 +1,371 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.ServiceProcess;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using WMI;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
namespace winsw
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// In-memory representation of the configuration file.
|
||||||
|
/// </summary>
|
||||||
|
public class ServiceDescriptor
|
||||||
|
{
|
||||||
|
private readonly XmlDocument dom = new XmlDocument();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Where did we find the configuration file?
|
||||||
|
///
|
||||||
|
/// This string is "c:\abc\def\ghi" when the configuration XML is "c:\abc\def\ghi.xml"
|
||||||
|
/// </summary>
|
||||||
|
public readonly string BasePath;
|
||||||
|
/// <summary>
|
||||||
|
/// The file name portion of the configuration file.
|
||||||
|
///
|
||||||
|
/// In the above example, this would be "ghi".
|
||||||
|
/// </summary>
|
||||||
|
public readonly string BaseName;
|
||||||
|
|
||||||
|
public static 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.Combine(AppDomain.CurrentDomain.BaseDirectory, p);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceDescriptor()
|
||||||
|
{
|
||||||
|
// find co-located configuration xml. We search up to the ancestor directories to simplify debugging,
|
||||||
|
// as well as trimming off ".vshost" suffix (which is used during debugging)
|
||||||
|
string p = ExecutablePath;
|
||||||
|
string baseName = Path.GetFileNameWithoutExtension(p);
|
||||||
|
if (baseName.EndsWith(".vshost")) baseName = baseName.Substring(0, baseName.Length - 7);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
p = Path.GetDirectoryName(p);
|
||||||
|
if (File.Exists(Path.Combine(p, baseName + ".xml")))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// register the base directory as environment variable so that future expansions can refer to this.
|
||||||
|
Environment.SetEnvironmentVariable("BASE", p);
|
||||||
|
|
||||||
|
BaseName = baseName;
|
||||||
|
BasePath = Path.Combine(p, BaseName);
|
||||||
|
|
||||||
|
dom.Load(BasePath + ".xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SingleElement(string tagName)
|
||||||
|
{
|
||||||
|
var n = dom.SelectSingleNode("//" + tagName);
|
||||||
|
if (n == null) throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
|
||||||
|
return Environment.ExpandEnvironmentVariables(n.InnerText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path to the executable.
|
||||||
|
/// </summary>
|
||||||
|
public string Executable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return SingleElement("executable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optionally specify a different Path to an executable to shutdown the service.
|
||||||
|
/// </summary>
|
||||||
|
public string StopExecutable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppendTags("stopexecutable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Arguments or multiple optional argument elements which overrule the arguments element.
|
||||||
|
/// </summary>
|
||||||
|
public string Arguments
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string arguments = AppendTags("argument");
|
||||||
|
|
||||||
|
if (arguments == null)
|
||||||
|
{
|
||||||
|
var tagName = "arguments";
|
||||||
|
var argumentsNode = dom.SelectSingleNode("//" + tagName);
|
||||||
|
|
||||||
|
if (argumentsNode == null)
|
||||||
|
{
|
||||||
|
if (AppendTags("startargument") == null)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Environment.ExpandEnvironmentVariables(argumentsNode.InnerText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Multiple optional startargument elements.
|
||||||
|
/// </summary>
|
||||||
|
public string Startarguments
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppendTags("startargument");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Multiple optional stopargument elements.
|
||||||
|
/// </summary>
|
||||||
|
public string Stoparguments
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppendTags("stopargument");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Combines the contents of all the elements of the given name,
|
||||||
|
/// or return null if no element exists.
|
||||||
|
/// </summary>
|
||||||
|
private string AppendTags(string tagName)
|
||||||
|
{
|
||||||
|
XmlNode argumentNode = dom.SelectSingleNode("//" + tagName);
|
||||||
|
|
||||||
|
if (argumentNode == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string arguments = "";
|
||||||
|
|
||||||
|
foreach (XmlNode argument in dom.SelectNodes("//" + tagName))
|
||||||
|
{
|
||||||
|
arguments += " " + argument.InnerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Environment.ExpandEnvironmentVariables(arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// LogDirectory is the service wrapper executable directory or the optionally specified logpath element.
|
||||||
|
/// </summary>
|
||||||
|
public string LogDirectory
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
XmlNode loggingNode = dom.SelectSingleNode("//logpath");
|
||||||
|
|
||||||
|
if (loggingNode != null)
|
||||||
|
{
|
||||||
|
return loggingNode.InnerText;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Path.GetDirectoryName(ExecutablePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logmode to 'reset', 'rotate' once or 'append' [default] the out.log and err.log files.
|
||||||
|
/// </summary>
|
||||||
|
public string Logmode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
XmlNode logmodeNode = dom.SelectSingleNode("//logmode");
|
||||||
|
|
||||||
|
if (logmodeNode == null)
|
||||||
|
{
|
||||||
|
return "append";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return logmodeNode.InnerText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optionally specified depend services that must start before this service starts.
|
||||||
|
/// </summary>
|
||||||
|
public string[] ServiceDependencies
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
System.Collections.ArrayList serviceDependencies = new System.Collections.ArrayList();
|
||||||
|
|
||||||
|
foreach (XmlNode depend in dom.SelectNodes("//depend"))
|
||||||
|
{
|
||||||
|
serviceDependencies.Add(depend.InnerText);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string[])serviceDependencies.ToArray(typeof(string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return SingleElement("id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Caption
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return SingleElement("name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return SingleElement("description");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if the service should when finished on shutdown.
|
||||||
|
/// </summary>
|
||||||
|
public bool BeepOnShutdown
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return dom.SelectSingleNode("//beeponshutdown") != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The estimated time required for a pending stop operation, in milliseconds (default 15 secs).
|
||||||
|
/// Before the specified amount of time has elapsed, the service should make its next call to the SetServiceStatus function
|
||||||
|
/// with either an incremented checkPoint value or a change in currentState. (see http://msdn.microsoft.com/en-us/library/ms685996.aspx)
|
||||||
|
/// </summary>
|
||||||
|
public int WaitHint
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
XmlNode waithintNode = dom.SelectSingleNode("//waithint");
|
||||||
|
|
||||||
|
if (waithintNode == null)
|
||||||
|
{
|
||||||
|
return 15000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return int.Parse(waithintNode.InnerText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time, in milliseconds (default 1 sec), before the service should make its next call to the SetServiceStatus function
|
||||||
|
/// with an incremented checkPoint value.
|
||||||
|
/// Do not wait longer than the wait hint. A good interval is one-tenth of the wait hint but not less than 1 second and not more than 10 seconds.
|
||||||
|
/// </summary>
|
||||||
|
public int SleepTime
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
XmlNode sleeptimeNode = dom.SelectSingleNode("//sleeptime");
|
||||||
|
|
||||||
|
if (sleeptimeNode == null)
|
||||||
|
{
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return int.Parse(sleeptimeNode.InnerText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if the service can interact with the desktop.
|
||||||
|
/// </summary>
|
||||||
|
public bool Interactive
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return dom.SelectSingleNode("//interactive") != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Environment variable overrides
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, string> EnvironmentVariables
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Dictionary<string, string> map = new Dictionary<string, string>();
|
||||||
|
foreach (XmlNode n in dom.SelectNodes("//env"))
|
||||||
|
{
|
||||||
|
string key = n.Attributes["name"].Value;
|
||||||
|
string value = Environment.ExpandEnvironmentVariables(n.Attributes["value"].Value);
|
||||||
|
map[key] = value;
|
||||||
|
|
||||||
|
Environment.SetEnvironmentVariable(key, value);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of downloads to be performed by the wrapper before starting
|
||||||
|
/// a service.
|
||||||
|
/// </summary>
|
||||||
|
public List<Download> Downloads
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<Download> r = new List<Download>();
|
||||||
|
foreach (XmlNode n in dom.SelectNodes("//download"))
|
||||||
|
{
|
||||||
|
r.Add(new Download(n));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,11 +46,13 @@
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Download.cs" />
|
||||||
<Compile Include="DynamicProxy.cs" />
|
<Compile Include="DynamicProxy.cs" />
|
||||||
<Compile Include="Main.cs">
|
<Compile Include="Main.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="ServiceDescriptor.cs" />
|
||||||
<Compile Include="Wmi.cs" />
|
<Compile Include="Wmi.cs" />
|
||||||
<Compile Include="WmiSchema.cs" />
|
<Compile Include="WmiSchema.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue