Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

WCF for Single Instance

3.29/5 (3 votes)
6 Nov 2009CPOL2 min read 37.8K   519  
How WCF can be used to create a single instance of an application

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:

  1. Application should able to identify if instances of itself are already running.
  2. 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:

Image 1

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.

Image 2

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.

C#
[ServiceContract]
public interface  IServiceContract
{
    /// <summary>
    /// Signals this instance.
    /// </summary>
    [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.

C#
[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.

C#
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
        {
            // wait for server to respond
            if (host != null && host.State == CommunicationState.Opened)
            {
                (factory as IContextChannel).OperationTimeout = new TimeSpan(1000);
            }
            //signal server that a new instance is selected
            proxy.Signal();
            return true;
        }
        catch (EndpointNotFoundException e)
        {
            //return false to indicate this instance is first instance
            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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)