I apologize that there's a bit of interdependency here because this code was authored to support Windows 7 jump lists in JinxBot, so it might not make the most sense....
The service contract is
IJinxBotSingleInstanceService. It is realized as a service in
InstanceManagementService (which is the hosted WCF service, created when I create my main window which marshals the call through
IJumpListWindowTarget and then actually handles the logic in
MainWindow lines 336-358) and
InstanceManagementClient (which is the client used to invoke the service when the second process realizes that it a second process).
The actual interaction occurs in the
Program class. The interesting lines are 51-64:
Process[] currentProcesses = (from p in Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName)
where p.Id != Process.GetCurrentProcess().Id
select p).ToArray();
if (currentProcesses.Length > 0)
{
IntPtr mainWindowHandle = currentProcesses[0].MainWindowHandle;
InstanceManagementClient client = new InstanceManagementClient(currentProcesses[0].Id);
if (mainWindowHandle != IntPtr.Zero)
{
UnsafeNativeMethods.ShowWindow(mainWindowHandle, 9); //SW_RESTORE=9
UnsafeNativeMethods.UpdateWindow(mainWindowHandle);
}
client.InvokeParameter(args);
}
Note the dependency on
UnsafeNativeMethods as well.
The things that you need to do then are:
1.) Create your service contract.
2.) Create your service realization.
3.) Create your client realization, including the channel interface and proxy.
4.) Modify your Main() method to create your global mutex, marshal your service endpoint, and handle the mutex-already-exists case.
This code should run in XP, Vista, and Win7 (I've tested it and it works on Win7). There might be catches for XP and Vista though:
1.) The way I've implemented service marshaling depends on process ID. On XP using fast user switching, there could be instances where Process.GetCurrentProcesses() returns processes from other users. That isn't the default for Win7/Vista because of UAC, but I need to fix that at some point, probably by getting the current session ID.
2.) The way I've implemented service marshaling also depends on local named pipes. In Vista, there was a problem doing this with Remoting, but I didn't experience a security issue with Windows 7.
LMK how that works or if you have errors.