using System.Runtime.InteropServices; using System.ServiceProcess; using System.Diagnostics; using System; using System.ServiceModel; namespace WpkgInstaller { public enum ServiceState { SERVICE_STOPPED = 0x00000001, SERVICE_START_PENDING = 0x00000002, SERVICE_STOP_PENDING = 0x00000003, SERVICE_RUNNING = 0x00000004, SERVICE_CONTINUE_PENDING = 0x00000005, SERVICE_PAUSE_PENDING = 0x00000006, SERVICE_PAUSED = 0x00000007, } [StructLayout(LayoutKind.Sequential)] public struct ServiceStatus { public int dwServiceType; public ServiceState dwCurrentState; public int dwControlsAccepted; public int dwWin32ExitCode; public int dwServiceSpecificExitCode; public int dwCheckPoint; public int dwWaitHint; }; public partial class WpkgInstaller : ServiceBase { [DllImport("advapi32.dll", SetLastError = true)] private static extern bool SetServiceStatus(System.IntPtr handle, ref ServiceStatus serviceStatus); public WpkgInstaller() { InitializeComponent(); OpenMessageChannel(); eventLog = new EventLog(); string eventSourceName = "WpkgInstaller Service"; string logName = "WpkgNotifier"; if (!EventLog.SourceExists(eventSourceName)) { EventLog.CreateEventSource(eventSourceName, logName); } eventLog.Source = eventSourceName; eventLog.Log = logName; } protected override void OnStart(string[] args) { ServiceStatus serviceStatus = new ServiceStatus { dwCurrentState = ServiceState.SERVICE_START_PENDING, dwWaitHint = 100000 }; SetServiceStatus(ServiceHandle, ref serviceStatus); // RunWpkgSync(); serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; SetServiceStatus(ServiceHandle, ref serviceStatus); eventLog.WriteEntry("Service started", EventLogEntryType.Information); } protected override void OnStop() { ServiceStatus serviceStatus = new ServiceStatus { dwCurrentState = ServiceState.SERVICE_STOP_PENDING, dwWaitHint = 100000 }; SetServiceStatus(ServiceHandle, ref serviceStatus); serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED; SetServiceStatus(ServiceHandle, ref serviceStatus); eventLog.WriteEntry("Service stopped", EventLogEntryType.Information); } private void RunWpkgSync() { eventLog.WriteEntry("Starting sync", EventLogEntryType.Information); RunWpkgCommand("/synchronize"); } private void RunWpkgQuery() { eventLog.WriteEntry("Starting query", EventLogEntryType.Information); RunWpkgCommand("/query:m"); } private void RunWpkgCommand(string arg) { Process process = new Process(); ProcessStartInfo startInfo = new ProcessStartInfo() { RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, WindowStyle = ProcessWindowStyle.Hidden, FileName = Environment.GetEnvironmentVariable("comspec"), Arguments = String.Format("/C \\\\wpkg.ch.cam.ac.uk\\wpkg\\wpkg.cmd {0}", arg), WorkingDirectory = Environment.GetEnvironmentVariable("temp"), UseShellExecute = false, }; process.StartInfo = startInfo; process.EnableRaisingEvents = true; process.OutputDataReceived += WriteStdoutToLog; process.ErrorDataReceived += WriteStderrToLog; process.Start(); process.BeginErrorReadLine(); process.BeginOutputReadLine(); process.WaitForExit(); String msg = String.Format("wpkg command finished, with exit code {0}", process.ExitCode); eventLog.WriteEntry(msg, EventLogEntryType.Information); } private void WriteStdoutToLog(object sendingProcess, DataReceivedEventArgs e) { if (e != null && e.Data != null) { eventLog.WriteEntry(e.Data, EventLogEntryType.Information); } } private void WriteStderrToLog(object sendingProcess, DataReceivedEventArgs e) { if (e != null && e.Data != null) { eventLog.WriteEntry(e.Data, EventLogEntryType.Error); } } private void eventLog_EntryWritten(object sender, EntryWrittenEventArgs e) { } private void OpenMessageChannel() { Uri BaseAddress = new Uri("net.pipe://localhost/www.ch.cam.ac.uk/WpkgNotifier"); NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); WpkgInstallerMessageService svc = new WpkgInstallerMessageService(); ServiceHost SvcHost = new ServiceHost(svc, BaseAddress); SvcHost.AddServiceEndpoint(typeof(IWpkgMessageRequestHandlerContract), binding, ""); SvcHost.Open(); (SvcHost.SingletonInstance as WpkgInstallerMessageService).WpkgEventCallback += new WpkgEventCallbackHandler(ProcessMessage); } private WpkgMessageRequestType ProcessMessage(object sender, WpkgMessageRequest e) { eventLog.WriteEntry(string.Format("Got {0}", e.Type)); switch(e.Type) { case WpkgMessageRequestType.DO_SYNC: RunWpkgSync(); break; case WpkgMessageRequestType.RUN_QUERY: RunWpkgQuery(); break; } return WpkgMessageRequestType.DONE; } } }