Search code examples
c#mutexsingle-instance

How to run one instance of a c# WinForm application?


I've a C# application that displays a login form when launched and displays the main form after users are authenticated. I used Mutex to restrict that only one instance of my application runs. And, this works fine for only the Login form. Once the main form is displayed, it doesn't restrict users from reopening the Login form. I was looking for a solution by which the Login screen couldn't be displayed once the main form is already opened.

Here is my Program.cs

 [STAThread]
    static void Main()
    {
        bool mutexCreated=true;

        using (Mutex mutex = new Mutex(true, "eCS", out mutexCreated))
        {
            if (mutexCreated)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Login());
            }
            else
            {
                Process current = Process.GetCurrentProcess();
                foreach (Process process in Process.GetProcessesByName(current.ProcessName))
                {
                    if (process.Id != current.Id)
                    {
                        XtraMessageBox.Show("Another instance of eCS is already running.", "eCS already running", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        SetForegroundWindow(process.MainWindowHandle);
                        break;
                    }
                }
            }
        }
    }

Solution

  • I've made some small changes:

    
    namespace CSMutex
    {
        static class Program
        {
            [STAThread]
            static void Main()
            {
                bool mutexCreated=true;
                using(Mutex mutex = new Mutex(true, "eCS", out mutexCreated))
                {
                    if (mutexCreated)
                    {
                        Application.EnableVisualStyles();
                        Application.SetCompatibleTextRenderingDefault(false);
                        Login loging = new Login();
                        Application.Run(loging);
                        Application.Run(new Main() { UserName = loging.UserName });
                    }
                    else
                    {
                        Process current = Process.GetCurrentProcess();
                        foreach (Process process in Process.GetProcessesByName(current.ProcessName))
                        {
                            if (process.Id != current.Id)
                            {
                                MessageBox.Show("Another instance of eCS is already running.", "eCS already running", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                //SetForegroundWindow(process.MainWindowHandle);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
    

    That works as expected - i.e. even when Login form is closed (and the main application form is started) it doesn't let user run the application once again. I've decided not to create Main from within Login (this is I believe how you application works) and instead I am passing parameter to Main. I have also made some small change to Login so it has UserName propert (same as Main).