Sunday, November 22, 2009

Single Winform Application

We wrote a production windows forms application. The requirement was that there can be only one instance of the application at any point in time. So we used Process.GetProcessByName as we knew the application name. We ran into the following problems :

1.)We didnt realize that there can be many processes with the same name. This can attributed to improper testing.
2.)Also GetProcessByName method needs admin access to execute.
3.)This is very costly method.

So what did we do?Use a named mutex. That too the name of the mutex that we chose had a GUID.If the application can acquire the named mutex with WaitOne, then it is the first instance running. If the application calls WaitOne and WaitOne returns false, another instance of the application is running and this one needs to exit.

This is what we did :


static class Program
    {

        private static string appGuid = new Guid().ToString();

        ///
        /// The main entry point for the application.
        ///

        [STAThread]
        static void Main()
        {
           
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Mutex mutex = new Mutex(false, appGuid);
            if (!mutex.WaitOne(0, false))
            {
                MessageBox.Show("Instance of applicationame is already running");
                return;
            }
            Application.Run(new Form1());
        }

Everything was good, until we deployed this in production. We were still able to create multiple instances but not as frequently as were able to do without the mutex. I am still trying to find out the reason behind this. So if anybody comes across this blog and has an answer to the above quetion please let me know.

We were able to solve the issue by keeping the mutex alive and disposing it off just before the application exits.

using (Mutex mutex = new Mutex(false, appGuid))
            {
                if (!mutex.WaitOne(0, false))
                {
                    MessageBox.Show("Instance already running");
                    return;
                }
                Application.Run(new Form1());
            }

Note that this is a local mutex and restricts creation of instances within the particular user session. To create a global mutex and make sure that there is only one instance across user sessions mutex needs to be created as following
using (Mutex mutex = new Mutex(false, @"Global\" + appGuid))

No comments:

Post a Comment