I currently support an internal application in .Net. The application uses IPC to simultaneously support one running session; if another session tries to open (someone clicks on the icon again, some open the file with the saved results), the second session transfers this to the first session, and then ends, and the first session starts the requested action.
I am currently using this System.ServiceModel namespace, for example:
namespace EventLogViewer.IPCServer {// Provides a common process structure for communicating with others.
[ServiceContract(Namespace = "http://ELV.domain")] interface IELVLauncher { [OperationContract] bool LaunchTabs(String[] fileNames); } public delegate void TabLauncher(String[] fileNames); class ELVLauncherServer : IDisposable { ServiceHost ipcService; public ELVLauncherServer() { Uri baseAddress = new Uri("Http://localhost:45600/elvlauncher/service"); String address = "net.pipe://localhost/elvlauncher/tablauncher"; ipcService = new ServiceHost(typeof(ELVLauncher), baseAddress); NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); ipcService.AddServiceEndpoint(typeof(IELVLauncher), binding, address); ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); behavior.HttpGetEnabled = true; behavior.HttpGetUrl = new Uri("http://localhost:45601/elvlauncher"); ipcService.Description.Behaviors.Add(behavior); Utilities.WriteMemoryDebugStatement(new DebugStatement(DebugStatement.StatementType.INFO, "Registering IPC Service")); ipcService.Open(); } #region IDisposable Members public void Dispose() { ipcService.Close(); } #endregion } public class ELVLauncher : IELVLauncher { #region IELVLauncher Members public bool LaunchTabs(string[] fileNames) { try { Utilities.WriteMemoryDebugStatement(new DebugStatement(DebugStatement.StatementType.INFO, String.Format("IPC request received, files: {0}", String.Join(", ", fileNames)))); Program.mainWindow.backgroundListener_OnLaunchRequestReceived(fileNames); } catch (Exception exception) { Utilities.WriteMemoryDebugStatement(new DebugStatement(exception)); } return (true); } #endregion }
This code was originally developed under Windows XP, like most corporations that we have not moved to Vista. Since we all act as local administrators, this code works without problems.
However, now we are moving to Win 7, and this code throws an exception at startup because it cannot register the IPC endpoint. More information here: http://mark.michaelis.net/Blog/WindowsCommunicationFoundationWithWindowsVistaAndUAC.aspx
The workaround is to add the application to the required administrative rights. This does not work for two reasons:
- This application does not need admins otherwise
- We use ClickOnce to deploy our internal tools, and ClickOnce does not support anything other than launching as a process startup.
So, at this moment I need to find an IPC solution that does not require administrator rights and allows me to achieve the original goal: to detect an already running code instance and tell him what to do, otherwise start it myself. Any suggestions on what to do (within .Net, without third-party solutions, please) will be highly appreciated.