6

I wrote a program in c# now I would like to know what is the proper way to prevent the program from starting if it is already running?

so if it is already running, and double-click on the program it will not start because it is already running.

I can do that, but I was thinking of a standard and proper way.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Data-Base
  • 8,418
  • 36
  • 74
  • 98

7 Answers7

10

The recommended way to do this is with a system mutex.

bool createdNew;
using(var mutex = new System.Threading.Mutex(true, "MyAppName", out createdNew))
{
    if (createdNew)
        // first instance
        Application.Run();
    else
        MessageBox.Show("There is already an instace running");
}

The first parameter to the Mutex ctor tells it to give create a system wide mutex for this thread. If the Mutex already exists it will return out false through the 3rd parameter.

Update
Where to put this? I'd put this in program.cs. If you put it in form_load you'll need to keep the mutex for the life time of the application (have the mutex as a member on the form), and manually release it in the form unload.
The earlier you call this the better, before the other app opens DB connections etc. and before resources are put created for forms / controlls etc.

Binary Worrier
  • 50,774
  • 20
  • 136
  • 184
  • 2
    I don't think that this is the *recommended way* if this already encapsulated in [WindowsFormsApplicationBase](http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.issingleinstance.aspx) – Oliver Aug 23 '10 at 07:20
  • this look cool, but http://msdn.microsoft.com/en-us/library/system.threading.mutex%28v=VS.80%29.aspx (Caution: An abandoned mutex indicates a serious error in the code. When a thread exits without releasing the mutex, the data structures protected by the mutex might not be in a consistent state. The next thread to request ownership of the mutex can handle this exception and proceed, if the integrity of the data structures can be verified.), what about this? I use .NET v2 – Data-Base Aug 23 '10 at 07:25
  • @Oliver: Thats in the VB namespace, this is a C# question. – Binary Worrier Aug 23 '10 at 07:26
  • @Data-Base: Apologies, should have wrapped mutex use with `using` – Binary Worrier Aug 23 '10 at 07:29
  • 2
    @BinaryWorrier - WindowsFormsApplicationBase is a standard part of the .NET framework, available on every installation. That VB is in the namespace is more an indication of which team wrote it than anything else. It works perfectly from a C# application - there's no reason to avoid it. – Bevan Aug 23 '10 at 07:36
  • Thanks, now where I should place the code, under form_load right? or there is a special thing I have to do? – Data-Base Aug 23 '10 at 07:38
  • @Binary Worrier and @Bevan: Yes, i think it was one of the greatest failures this team could make. If they had named their namespace `ConvenientFunctions` instead of `VisualBasic` it would be far more popular. – Oliver Aug 23 '10 at 07:52
4

Quick way I did in one of the applications .. You can look at the list of running processes to see whether the current application is already running and not start the application again.

Process[] lprcTestApp = Process.GetProcessesByName("TestApplication");
if (lprcTestApp.Length > 0)
{
      // The TestApplication is already running, don't run it again
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Premkumar
  • 111
  • 1
  • 8
2

I think enumerating the process list could potentially be slow. You could also create a Mutex using the System.Threading.Mutex class and check to see if it's already created when the process starts. However, this would require calling into Win32 system code so wouldn't be completely platform agnostic.

Mike Christensen
  • 88,082
  • 50
  • 208
  • 326
2

Take a look at Scotts blog post and don't be foolished by the assembly name. It's just a file name of a standard file in the .Net framework.

Here are more informations direct out of MSDN for the WindowsFormsApplicationBase.

Oliver
  • 43,366
  • 8
  • 94
  • 151
0

You can use a system-wide Semaphore, using the Semaphore Constructor (Int32, Int32, String, Boolean%) constructor and a fairly unique name.

Cheers, Matthias

Matthias Meid
  • 12,455
  • 7
  • 45
  • 79
0

If your application produces/consumes files, then you're better registering a system wide communication mechanism (e.g. a remoting or WCF endpoint, or even a socket). Then, if the second instance of the application is being launched from double clicking one of your files, you can send the file information across to the running instance.

Otherwise, if it's a standalone program, then as others have said, a Mutex or Semaphore would server equally well.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
0

solution in Windows form application Prohibit again run application(reopen application).

1- first add Class RunAlready.cs

2-Call method processIsRunning() with Name Process from RunAlready.cs in Program.cs

Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Tirage.MainStand
{
static class Program
{

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        PublicClass.Class.RunAlready RunAPP = new PublicClass.Class.RunAlready();
        string outApp = RunAPP.processIsRunning("Tirage.MainStand");

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        MainStand_FrmLogin fLogin = new MainStand_FrmLogin();
        if (outApp.Length == 0)
        {

            if (fLogin.ShowDialog() == DialogResult.OK)
            {
                Application.Run(new MainStand_masterFrm());

            }
        }
        else MessageBox.Show( "Instance already running");

      }
    }
 }

class RunAlready:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PublicClass.Class
{
  public  class RunAlready
    {
      public  string processIsRunning(string process)
        {
        string xdescription = "";
        System.Diagnostics.Process[] processes =
            System.Diagnostics.Process.GetProcessesByName(process);
        foreach (System.Diagnostics.Process proc in processes)
        {
            var iddd = System.Diagnostics.Process.GetCurrentProcess().Id;
            if (proc.Id != System.Diagnostics.Process.GetCurrentProcess().Id)
            {
                xdescription = "Application Run At time:" + proc.StartTime.ToString() + System.Environment.NewLine;
                xdescription += "Current physical memory : " + proc.WorkingSet64.ToString() + System.Environment.NewLine;
                xdescription += "Total processor time : " + proc.TotalProcessorTime.ToString() + System.Environment.NewLine;
                xdescription += "Virtual memory size : " +         proc.VirtualMemorySize64.ToString() + System.Environment.NewLine;
            }
        }


        return xdescription;
    }
}
}