I currently maintain an internal application in .Net. The application uses IPC to maintain one running session at a time; if another session attempt to open (Someone clicks the icon again, some opens up a saved result file), the second session communicates this to the first session and then terminates, with the first session then launching the requested action.
I currently do this using the the System.ServiceModel namespace, like so:
namespace EventLogViewer.IPCServer { //Provides the common framework for processes to communicate to oneanother.
[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, as like most corporations we did not move to Vista. Since we all run as local admins, this code ran without a problem.
However, we are transitioning to Win 7 now, and this code produces an exception on startup because it cannot register the IPC endpoint. More information is here: http://mark.michaelis.net/Blog/WindowsCommunicationFoundationWithWindowsVistaAndUAC.aspx
The workaround given is to up the app to requiring admin privledges. This doesn't work for two reasons:
So at this point I need to find an IPC solution which does not require admin privledges and lets me achieve the original goal: detecting an already running instance of the code and telling it what to do, otherwise launching itself. Any suggestions on what to do (within the .Net framework, no 3rd party solutions please) would be much appreciated.
That is an incredibly difficult (and as you have discovered, problematic way) to ensure a single session of your app. You should just refactor/redo the feature to use a mutex.
Here is another example. And the requisite wiki article about mutexes.
EDIT
To get around the communication bit you could generate a temp file with your own special prefix and or extension in OS-provided temp folder which the single app would poll (filtering for your special prefix and/or extension) to see whether more requests were made. See:
System.IO.Path.GetTempFileName
and
System.IO.Path.GetTempPath
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With