diff --git a/Main.cs b/Main.cs index a424751..32d777b 100644 --- a/Main.cs +++ b/Main.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.ServiceProcess; using System.Text; using System.IO; +using System.Net; using WMI; using System.Xml; using System.Threading; @@ -372,6 +373,63 @@ namespace winsw return map; } } + + /// + /// List of downloads to be performed by the wrapper before starting + /// a service. + /// + public List Downloads + { + get + { + List r = new List(); + foreach (XmlNode n in dom.SelectNodes("//download")) + { + r.Add(new Download(n)); + } + return r; + } + } + } + + /// + /// Specify the download activities prior to the launch. + /// This enables self-updating services. + /// + public class Download + { + public readonly string From; + public readonly string To; + + internal Download(XmlNode n) + { + From = n.Attributes["from"].Value; + To = 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 + 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) return; + o.Write(buf, 0, len); + } + i.Close(); + o.Close(); + } } public class WrapperService : ServiceBase @@ -546,9 +604,24 @@ namespace winsw { LogEvent("envar " + key + '=' + envs[key]); } - + HandleFileCopies(); + // handle downloads + foreach (Download d in descriptor.Downloads) + { + LogEvent("Downloading: " + d.From+ " to "+d.To); + try + { + d.Perform(); + } + catch (Exception e) + { + LogEvent("Failed to download " + d.From, EventLogEntryType.Warning); + // but just keep going + } + } + string startarguments = descriptor.Startarguments; if (startarguments == null)