4

I have a windows application (C#) and i need to configure it to run one instance from the application at the time , It means that one user clicked the .exe file and the application is run and the user didn't close the first instance of the application that is being run and need to run a next instance so it should appear the first instance and not opening new one.

can any one help me how to do that?

thanks in advance

Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
Ahmy
  • 5,420
  • 8
  • 39
  • 50

7 Answers7

10

I often solve this by checking for other processes with the same name. The advantage/disadvantage with this is that you (or the user) can "step aside" from the check by renaming the exe. If you do not want that you could probably use the Process-object that is returned.

  string procName = Process.GetCurrentProcess().ProcessName;
  if (Process.GetProcessesByName(procName).Length == 1)
  {
      ...code here...
  }

It depends on your need, I think it's handy to bypass the check witout recompiling (it's a server process, which sometimes is run as a service).

kaze
  • 4,299
  • 12
  • 53
  • 74
  • This method cannot be used by partially trusted code. As a global C# example this is a poor approach. – MBender Nov 25 '16 at 08:55
4

The VB.Net team has already implemented a solution. You will need to take a dependency on Microsoft.VisualBasic.dll, but if that doesn't bother you, then this is a good solution IMHO. See the end of the following article: Single-Instance Apps

Here's the relevant parts from the article:

1) Add a reference to Microsoft.VisualBasic.dll 2) Add the following class to your project.

public class SingleInstanceApplication : WindowsFormsApplicationBase
{
    private SingleInstanceApplication()
    {
        base.IsSingleInstance = true;
    }

    public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
    {
        SingleInstanceApplication app = new SingleInstanceApplication();
        app.MainForm = f;
        app.StartupNextInstance += startupHandler;
        app.Run(Environment.GetCommandLineArgs());
    }
}

Open Program.cs and add the following using statement:

using Microsoft.VisualBasic.ApplicationServices;

Change the class to the following:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        SingleInstanceApplication.Run(new Form1(), StartupNextInstanceEventHandler);
    }

    public static void StartupNextInstanceEventHandler(object sender, StartupNextInstanceEventArgs e)
    {
        MessageBox.Show("New instance");
    }
}
Kim Major
  • 3,681
  • 1
  • 22
  • 20
  • 2
    This is a simple approach, however it comes with the pitfalls mentioned in the discussion in Scott Hanselman's blog post: http://www.hanselman.com/blog/TheWeeklySourceCode31SingleInstanceWinFormsAndMicrosoftVisualBasicdll.aspx – Dirk Vollmar May 26 '09 at 17:57
  • Thanks for pointing this out, I wasn't aware of that. I could only see one pitfall in the linked post and that was that this solution won't work when windows is running in safe mode. Many applications have functionality that requires running in normal mode anyhow, and then this might not be much of a drawback. Anyhow, it's good to know that there is an issue. – Kim Major May 26 '09 at 18:33
1

Edit : After the question was amended to include c#. My answer works only for vb.net application

select the Make single instance application check box to prevent users from running multiple instances of your application. The default setting for this check box is cleared, allowing multiple instances of the application to be run.

You can do this from Project -> Properties -> Application tab

Source

Shoban
  • 22,920
  • 8
  • 63
  • 107
1

We had exactly the same problem. We tried the process approach, but this fails, if the user has no right to read information about other processes, i.e. non-admins. So we implemented the solution below.

Basically we try to open a file for exclusive reading. If this fails (because anohter instance has already done this), we get an exception and can quit the app.

        bool haveLock = false;
        try
        {
            lockStream = new System.IO.FileStream(pathToTempFile,System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite,System.IO.FileShare.None);
            haveLock = true;
        }
        catch(Exception)
        {
            System.Console.WriteLine("Failed to acquire lock. ");
        }
        if(!haveLock)
        {
            Inka.Controls.Dialoge.InkaInfoBox diag = new Inka.Controls.Dialoge.InkaInfoBox("App has been started already");
            diag.Size = new Size(diag.Size.Width + 40, diag.Size.Height + 20);
            diag.ShowDialog();
            Application.Exit();
        }
Mario
  • 183
  • 2
  • 6
0

I'd use a Mutex for this scenario. Alternatively, a Semaphore would also work (but a Mutex seems more apt).

Here's my example (from a WPF application, but the same principles should apply to other project types):

public partial class App : Application
{
    const string AppId = "MY APP ID FOR THE MUTEX";
    static Mutex mutex = new Mutex(false, AppId);
    static bool mutexAccessed = false;

    protected override void OnStartup(StartupEventArgs e)
    {
        try
        {
            if (mutex.WaitOne(0))
                mutexAccessed = true;
        }
        catch (AbandonedMutexException)
        {
            //handle the rare case of an abandoned mutex
            //in the case of my app this isn't a problem, and I can just continue
            mutexAccessed = true;
        }

        if (mutexAccessed)
            base.OnStartup(e);
        else
            Shutdown();
    }

    protected override void OnExit(ExitEventArgs e)
    {
        if (mutexAccessed)
            mutex?.ReleaseMutex();

        mutex?.Dispose();
        mutex = null;
        base.OnExit(e);
    }
}
MBender
  • 5,395
  • 1
  • 42
  • 69
0

I found this code, it's work!

 /// <summary>
        /// The main entry point for the application.
        /// Limit an app.to one instance
        /// </summary>
        [STAThread]
        static void Main()
        {
            //Mutex to make sure that your application isn't already running.
            Mutex mutex = new System.Threading.Mutex(false, "MyUniqueMutexName");
            try
            {
                if (mutex.WaitOne(0, false))
                {
                    // Run the application
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                }
                else
                {
                    MessageBox.Show("An instance of the application is already running.",
                        "An Application Is Running", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Application Error 'MyUniqueMutexName'", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            finally
            {
                if (mutex != null)
                {
                    mutex.Close();
                    mutex = null;
                }
            }
        }
Bob
  • 67
  • 1
0

Assuming you are using C#

        static Mutex mx;
        const string singleInstance = @"MU.Mutex";
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {
                System.Threading.Mutex.OpenExisting(singleInstance);
                MessageBox.Show("already exist instance");
                return;
            }
            catch(WaitHandleCannotBeOpenedException)
            {
                mx = new System.Threading.Mutex(true, singleInstance);

            }
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
Ahmed
  • 7,148
  • 12
  • 57
  • 96