Introduction
Some applications would like to have single instance running at any time.
To create a single instance application, there are two requirements to be matched:
- Application should able to identify if instances of itself are already running.
- If so, notify the first instance and let the first instance handle the situation instead.
As the two instances are two different processes altogether, it involves inter process communication. WCF is one of the simpler approaches among many (like using WindowsFormsApplicationBase
, IPC and remoting) to solve this problem.
Using the Code
The sample application contains two windows. One is a start up form that launches employee details entry form through which employee details can be saved to XML file.
The requirement is that the application shall open employee details form each time it is run. For the first time, it usually opens up the form.
When another instance is invoked, the first instance will be informed of the second instance, and prompts the user whether to close the form as shown in the below figure:
Based on user response, it either closes old form or opens a new employee details form (notice encircled form title in the below figure).
Thus each time the application is run; only one form will be opened.
Now let’s look into the code…
Define an interface through which client (another instance) can communicate with server (first instance).
Decorate the interface as “ServiceContract
” to expose it to client.
Methods that are decorated as “ OperationContract
” alone will be visible to client.
Through Signal()
method, the client communicates to the server.
[ServiceContract]
public interface IServiceContract
{
[OperationContract]
void Signal();
}
“Service
” Class implements the above contract.
Notice InstanceContextMode
is set to Single
. This is required if a service instance is passed to service host.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service : IServiceContract
{
public EmployeeDetailsWindow window;
private static int formNumber;
void IServiceContract.Signal()
{
string strText = "Other instance is selected.\n";
strText =strText +"Do you want to close this and open the other ?";
MessageBoxResult result =
MessageBox.Show(strText, "Close", MessageBoxButton.YesNo);
bool blnInstanceClosed =
result == MessageBoxResult.Yes ? true : false;
if (blnInstanceClosed)
{
CloseEmployeeWindow();
Run();
}
else
{
if (window != null)
window.Activate();
}
}
}
InstanceMutex
class has two functions “IsInstanceRunning
” and “St<code>
artService”.
When “IsInstanceRunning
” requests for a channel, if it does not exist “EndPointNotFoundException
” is thrown.
Which means this is the first instance. And it has to become the server by calling “StartService
”.
“StartService
” creates service host and opens it to serve the requests.
public class InstanceMutex
{
public static ServiceHost host;
public static bool IsInstanceRunning(string channelUri)
{
ChannelFactory<IServiceContract> factory =
new ChannelFactory<IServiceContract>
(new NetNamedPipeBinding(), new EndpointAddress(channelUri));
IServiceContract proxy = factory.CreateChannel();
try
{
if (host != null && host.State == CommunicationState.Opened)
{
(factory as IContextChannel).OperationTimeout = new TimeSpan(1000);
}
proxy.Signal();
return true;
}
catch (EndpointNotFoundException e)
{
return false;
}
}
public static void StartService(IServiceContract instance, string channelUri)
{
host = new ServiceHost(instance, new Uri(channelUri));
try
{
host.AddServiceEndpoint
(typeof(IServiceContract), new NetNamedPipeBinding(), new Uri(channelUri));
host.Open();
(instance as Service).LaucnhStartUpWindow();
}
catch (CommunicationException ex)
{
host.Abort();
}
}
}
Now if another instance is selected, “IsInstanceRunning
” gets channel to end point and signals the first instance. And then the first instance does the necessary actions.
After signaling, the second instance shuts down. Hence always a single instance of the application exists.
History
- 6th November, 2009: Initial version