diff --git a/WpkgInstaller/IWpkgMessageCallbackHandlerContract.cs b/WpkgInstaller/IWpkgMessageCallbackHandlerContract.cs deleted file mode 100755 index d277d59121523dbed3ae7a04ebe0b3813cf89870..0000000000000000000000000000000000000000 --- a/WpkgInstaller/IWpkgMessageCallbackHandlerContract.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.ServiceModel; - -namespace WpkgInstaller -{ - public interface IWpkgMessageCallbackHandlerContract - { - [OperationContract(IsOneWay = true)] - void HandleResponse(WpkgMessageResponse response); - - [OperationContract(IsOneWay = true)] - void HandleMessage(WpkgMessageState status); - } -} diff --git a/WpkgInstaller/IWpkgMessageRequestHandlerContract.cs b/WpkgInstaller/IWpkgMessageRequestHandlerContract.cs deleted file mode 100644 index e6bc7746cc6e0c0df3839f1ef8de67cd2adb2e23..0000000000000000000000000000000000000000 --- a/WpkgInstaller/IWpkgMessageRequestHandlerContract.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ServiceModel; - -namespace WpkgInstaller -{ - public delegate WpkgMessageRequestType WpkgEventCallbackHandler(object sender, WpkgMessageRequest e); - - [ServiceContract(Namespace = "https://www.ch.cam.ac.uk/WpkgNotifier", - SessionMode = SessionMode.Required, - CallbackContract = typeof(IWpkgMessageCallbackHandlerContract))] - public interface IWpkgMessageRequestHandlerContract - { - [OperationContract(IsOneWay = true)] - void HandleMessage(WpkgMessageRequestType type); - } -} diff --git a/WpkgInstaller/IWpkgNotifierMessageClient.cs b/WpkgInstaller/IWpkgNotifierMessageClient.cs new file mode 100755 index 0000000000000000000000000000000000000000..3e8bcb93c081fa692a941c1cc501cd3db48e8499 --- /dev/null +++ b/WpkgInstaller/IWpkgNotifierMessageClient.cs @@ -0,0 +1,13 @@ +using System.ServiceModel; + +namespace WpkgInstaller +{ + public interface IWpkgNotifierMessageClient + { + [OperationContract(IsOneWay = true)] + void StatusLine(string msg); + + [OperationContract(IsOneWay = true)] + void SetStatus(WpkgMessageState status); + } +} \ No newline at end of file diff --git a/WpkgInstaller/IWpkgNotifierMessageServer.cs b/WpkgInstaller/IWpkgNotifierMessageServer.cs new file mode 100755 index 0000000000000000000000000000000000000000..b1ec47cfc04c266898e212f3b3ff2377ab7c55cd --- /dev/null +++ b/WpkgInstaller/IWpkgNotifierMessageServer.cs @@ -0,0 +1,18 @@ +using System.ServiceModel; + +namespace WpkgInstaller +{ + + [ServiceContract(CallbackContract = typeof(IWpkgNotifierMessageClient))] + public interface IWpkgNotifierMessageServer + { + [OperationContract(IsOneWay = true)] + void Register(int pid); + + [OperationContract(IsOneWay = true)] + void Unregister(int pid); + + [OperationContract(IsOneWay = true)] + void ProcessRequest(WpkgMessageRequestType type); + } +} diff --git a/WpkgInstaller/WpkgInstaller.cs b/WpkgInstaller/WpkgInstaller.cs index d522ba96455679e497ffbe9b3cf4e6f23613d7df..31f161b74d6b05f9c4717a75bfb514c0c6226d71 100644 --- a/WpkgInstaller/WpkgInstaller.cs +++ b/WpkgInstaller/WpkgInstaller.cs @@ -3,6 +3,8 @@ using System.ServiceProcess; using System.Diagnostics; using System; using System.ServiceModel; +using System.Collections; +using System.Collections.Generic; namespace WpkgInstaller { @@ -28,18 +30,21 @@ namespace WpkgInstaller public int dwCheckPoint; public int dwWaitHint; }; - public partial class WpkgInstaller : ServiceBase + + [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] + public partial class WpkgInstaller : ServiceBase, IWpkgNotifierMessageServer { [DllImport("advapi32.dll", SetLastError = true)] private static extern bool SetServiceStatus(System.IntPtr handle, ref ServiceStatus serviceStatus); + private Dictionary<int, IWpkgNotifierMessageClient> clients; - private IWpkgMessageCallbackHandlerContract notifierCallbackHandler; public WpkgInstaller() { InitializeComponent(); eventLog = new EventLog(); + clients = new Dictionary<int, IWpkgNotifierMessageClient>(); string eventSourceName = "WpkgInstaller Service"; string logName = "WpkgNotifier"; @@ -88,14 +93,12 @@ namespace WpkgInstaller private void RunWpkgSync() { - notifierCallbackHandler.HandleMessage(WpkgMessageState.SYNCING); eventLog.WriteEntry("Starting sync", EventLogEntryType.Information); RunWpkgCommand("/synchronize"); } private void RunWpkgQuery() { - notifierCallbackHandler.HandleMessage(WpkgMessageState.QUERYING); eventLog.WriteEntry("Starting query", EventLogEntryType.Information); RunWpkgCommand("/query:m"); } @@ -127,15 +130,13 @@ namespace WpkgInstaller process.BeginOutputReadLine(); process.WaitForExit(); - notifierCallbackHandler.HandleMessage(WpkgMessageState.IDLE); - if(process.ExitCode == 0) { - notifierCallbackHandler.HandleMessage(WpkgMessageState.SUCCESS); + SetClientsState(WpkgMessageState.SUCCESS); } else { - notifierCallbackHandler.HandleMessage(WpkgMessageState.ERROR); + SetClientsState(WpkgMessageState.ERROR); } String msg = String.Format("wpkg command finished, with exit code {0}", process.ExitCode); eventLog.WriteEntry(msg, EventLogEntryType.Information); @@ -146,8 +147,7 @@ namespace WpkgInstaller { if (e != null && e.Data != null) { - notifierCallbackHandler.HandleResponse(new WpkgMessageResponse(e.Data)); - //eventLog.WriteEntry(e.Data, EventLogEntryType.Information); + // sent e.Data back to clients } } @@ -170,44 +170,83 @@ namespace WpkgInstaller { try { - Uri BaseAddress = new Uri("net.pipe://localhost/www.ch.cam.ac.uk/WpkgNotifier"); + Uri uri = new Uri("net.pipe://localhost/www.ch.cam.ac.uk/WpkgNotifier"); NetNamedPipeBinding binding = new NetNamedPipeBinding(); + ServiceHost serviceHost = new ServiceHost(this, uri); + serviceHost.AddServiceEndpoint(typeof(IWpkgNotifierMessageServer), binding, ""); + + serviceHost.Open(); - WpkgInstallerMessageService svc = new WpkgInstallerMessageService(); - ServiceHost SvcHost = new ServiceHost(svc, BaseAddress); - SvcHost.AddServiceEndpoint(typeof(IWpkgMessageRequestHandlerContract), binding, ""); - SvcHost.Open(); + eventLog.WriteEntry("serviceHost now open"); - (SvcHost.SingletonInstance as WpkgInstallerMessageService).WpkgEventCallback += new WpkgEventCallbackHandler(ProcessMessage); } catch (Exception e) { - eventLog.WriteEntry(e.Message); + eventLog.WriteEntry(e.Message, EventLogEntryType.Error); + throw e; } } - private WpkgMessageRequestType ProcessMessage(object sender, WpkgMessageRequest e) + public void Register(int pid) { - if (notifierCallbackHandler == null) + eventLog.WriteEntry(String.Format("Register requested for {0}", pid)); + IWpkgNotifierMessageClient client = OperationContext.Current.GetCallbackChannel <IWpkgNotifierMessageClient>(); + clients.Add(pid, client); + + foreach(KeyValuePair<int, IWpkgNotifierMessageClient> kv in clients) { - notifierCallbackHandler = OperationContext.Current.GetCallbackChannel<IWpkgMessageCallbackHandlerContract>(); + try + { + kv.Value.StatusLine(String.Format("Register requested for {0}", pid)); + } + catch (Exception e) + { + eventLog.WriteEntry("Error communicating with client " + kv.Key + " " + e.ToString(), EventLogEntryType.Warning); + } } + } - eventLog.WriteEntry(string.Format("Got {0}", e.Type)); - switch(e.Type) + public void Unregister(int pid) + { + if(clients.Remove(pid)) + { + eventLog.WriteEntry(String.Format("Client {0} unregistered", pid)); + } + else + { + eventLog.WriteEntry(String.Format("Unknown client {0} requested to unregister", pid), EventLogEntryType.Warning); + } + } + public void ProcessRequest(WpkgMessageRequestType type) + { + switch (type) { case WpkgMessageRequestType.DO_SYNC: + SetClientsState(WpkgMessageState.SYNCING); RunWpkgSync(); break; case WpkgMessageRequestType.RUN_QUERY: + SetClientsState(WpkgMessageState.QUERYING); RunWpkgQuery(); break; } - return WpkgMessageRequestType.DONE; - + } + private void SetClientsState(WpkgMessageState state) + { + foreach (KeyValuePair<int, IWpkgNotifierMessageClient> kv in clients) + { + try + { + kv.Value.SetStatus(state); + } + catch (Exception e) + { + eventLog.WriteEntry("Error communicating with client " + kv.Key + " " + e.ToString(), EventLogEntryType.Warning); + } + } } } } diff --git a/WpkgInstaller/WpkgInstaller.csproj b/WpkgInstaller/WpkgInstaller.csproj index 31ed41a0e3f6238f978ad69503ef0e735dcec473..2c6b5697deb58b9f1444d34a4444db8236b2f40b 100644 --- a/WpkgInstaller/WpkgInstaller.csproj +++ b/WpkgInstaller/WpkgInstaller.csproj @@ -70,7 +70,8 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> - <Compile Include="IWpkgMessageCallbackHandlerContract.cs" /> + <Compile Include="IWpkgNotifierMessageClient.cs" /> + <Compile Include="IWpkgNotifierMessageServer.cs" /> <Compile Include="ProjectInstaller.cs"> <SubType>Component</SubType> </Compile> @@ -85,8 +86,6 @@ </Compile> <Compile Include="Program.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="WpkgInstallerMessageService.cs" /> - <Compile Include="IWpkgMessageRequestHandlerContract.cs" /> <Compile Include="WpkgMessageRequest.cs" /> <Compile Include="WpkgMessageResponse.cs" /> <Compile Include="WpkgMessageState.cs" /> diff --git a/WpkgInstaller/WpkgInstallerMessageService.cs b/WpkgInstaller/WpkgInstallerMessageService.cs deleted file mode 100644 index bf72e2d8df5a16bcfba167db12d14e69f9435d0e..0000000000000000000000000000000000000000 --- a/WpkgInstaller/WpkgInstallerMessageService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ServiceModel; - -namespace WpkgInstaller -{ - [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] - class WpkgInstallerMessageService : IWpkgMessageRequestHandlerContract - { - public event WpkgEventCallbackHandler WpkgEventCallback = delegate { return WpkgMessageRequestType.DONE; }; - - public void HandleMessage(WpkgMessageRequestType type) - { - WpkgEventCallback(this, new WpkgMessageRequest(type)); - } - } -} diff --git a/WpkgNotifier/TrayNotifier.cs b/WpkgNotifier/TrayNotifier.cs index a6b9a0916f61f43c8b88227fac7d598c123ce939..64855fa4b0ba8b5ef569e78bcd3b8122b694e32f 100644 --- a/WpkgNotifier/TrayNotifier.cs +++ b/WpkgNotifier/TrayNotifier.cs @@ -8,16 +8,20 @@ using WpkgInstaller; namespace WpkgNotifier { - class TrayNotifier : ApplicationContext, IWpkgMessageCallbackHandlerContract + class TrayNotifier : ApplicationContext, IWpkgNotifierMessageClient { private NotifyIcon notifyIcon; - private IWpkgMessageRequestHandlerContract messageChannel; + private EventLog eventLog; private WpkgMessageState state; + private IWpkgNotifierMessageServer server; + private int pid; public TrayNotifier() { - + Process currentProcess = Process.GetCurrentProcess(); + pid = currentProcess.Id; + eventLog = new EventLog(); string eventSourceName = "TrayNotifier"; string logName = "WpkgNotifier"; @@ -33,6 +37,8 @@ namespace WpkgNotifier OpenMessageChannel(); + Application.ApplicationExit += new EventHandler(this.OnApplicationExit); + MenuItem actionsMenu = new MenuItem("Actions"); MenuItem syncMenuItem = new MenuItem("Sync", new EventHandler(RequestSync)); MenuItem queryMenuItem = new MenuItem("Query", new EventHandler(RequestQuery)); @@ -64,24 +70,30 @@ namespace WpkgNotifier }; } + private void OnApplicationExit(object sender, EventArgs e) + { + server.Unregister(pid); + } + private void OpenMessageChannel() { eventLog.WriteEntry("Trying to open channel"); try { - string address = "net.pipe://localhost/www.ch.cam.ac.uk/WpkgNotifier"; - NetNamedPipeBinding binding = new NetNamedPipeBinding(); + string uri = "net.pipe://localhost/www.ch.cam.ac.uk/WpkgNotifier"; InstanceContext context = new InstanceContext(this); - DuplexChannelFactory<IWpkgMessageRequestHandlerContract> factory = new DuplexChannelFactory<IWpkgMessageRequestHandlerContract>(context, binding, address); + DuplexChannelFactory<IWpkgNotifierMessageServer> channelFactory = + new DuplexChannelFactory<IWpkgNotifierMessageServer>(context, binding, uri); - messageChannel = factory.CreateChannel(); + server = channelFactory.CreateChannel(); eventLog.WriteEntry("channel created"); + server.Register(pid); + eventLog.WriteEntry("Registered with server"); } catch (Exception e) { eventLog.WriteEntry("problem creating channel"); - eventLog.WriteEntry(e.Message); } } @@ -89,13 +101,13 @@ namespace WpkgNotifier void RequestSync(object sender, EventArgs e) { notifyIcon.ContextMenu.MenuItems[0].Enabled = false; - messageChannel.HandleMessage(WpkgMessageRequestType.DO_SYNC); + server.ProcessRequest(WpkgMessageRequestType.DO_SYNC); } void RequestQuery(object sender, EventArgs e) { notifyIcon.ContextMenu.MenuItems[0].Enabled = false; - messageChannel.HandleMessage(WpkgMessageRequestType.RUN_QUERY); + server.ProcessRequest(WpkgMessageRequestType.RUN_QUERY); } void ManageSoftware(object sender, EventArgs e) @@ -111,6 +123,8 @@ namespace WpkgNotifier Application.Exit(); } + + public void SetToolTip(string msg) { notifyIcon.Text = msg; @@ -121,7 +135,7 @@ namespace WpkgNotifier eventLog.WriteEntry(response.Message); } - public void HandleMessage(WpkgMessageState status) + public void SetStatus(WpkgMessageState status) { this.state = status; switch (status) @@ -145,5 +159,10 @@ namespace WpkgNotifier break; } } + + public void StatusLine(string msg) + { + SetToolTip(msg); + } } }