Clear Night Software

How to ensure only one copy of your program runs at a time.

Jump to Visual C++ / MFC

Visual Basic:

Check the PrevInstance property of the App object to determine whether another instance of your program was already running before the current one started.

If you don't want more than one instance to run, place this code at the start of the Form_Load event of your startup form, or in your Main subroutine:

    If App.PrevInstance Then End

Now a warning... (from the Visual Basic Help File)
Since a computer running Windows NT can support multiple desktops, if you use a component designed to work with distributed COM, it can result in the following scenario:
  • A client program in a user desktop requests one of the objects the component provides. Because the component is physically located on the same machine, the component is started in the user desktop.
  • Subsequently, a client program on another computer uses distributed COM to request one of the objects the component provides. A second instance of the component is started, in a system desktop.
  • There are now two instances of the component running on the same NT computer, in different desktops.
    This scenario is not a problem unless the author of the component has placed a test for App.PrevInstance in the startup code for the component to prevent multiple copies of the component from running on the same computer. In this case, the remote component creation will fail.
    Now a warning... (from me)
    PrevInstance will not detect a different version of your program that is already running. It won't even detect an identical copy of the same program from a different disk folder.
    For example, if you are already running "C:\Development\MyApp.exe", and you start "C:\Program Files\MyApp\MyApp.exe", PrevInstance will be false.
    There are other ways to use the PrevInstance property.
    This example is from Clear Night Software's Random Wallpaper:
    Sub main()
        ...    
        If App.PrevInstance Then
            MsgBox App.EXEName & " is already running.  Right-click the 'Random Wallpaper' " & _
                   "icon in the System Tray to control it"
            End
        End If
        ...
    End Sub
    
    Or you may wish to allow several instances of a program to run, but assign a specialised role to the first instance.
    Private Sub Form_Load()
        If Not App.PrevInstance Then
            ' I am the first/only instance running I'll handle co-ordination
            SaveSetting App.EXEName, "Settings", "Lock", "Locked"
            boolBoss = True
        Else
            boolBoss = False
        End If
        ...
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        If boolBoss Then
            SaveSetting App.EXEName, "Settings", "Lock", "Unlocked"
        End If
        DoEvents
    End Sub
    
    Private Sub Timer1_Timer()
        If Not boolBoss Then    ' check if someone else is handling this
            If GetSetting(App.EXEName, "Settings", "Lock") = "Unlocked" Then
                ' No one's doing it so I will
                SaveSetting App.EXEName, "Settings", "Lock", "Locked"
                boolBoss = True
            End If
        End If
        If boolBoss Then
            ' Do co-ordination stuff
            ...
        End If
    End Sub
    

    The code outlined above lets you have multiple instances of a program running, but only the first instance will execute the "co-ordination stuff" in the timer subroutine.

    If the first instance is shut down, but other instances are still running, one of them will take over the co-ordination role.


    Visual C++ / MFC:

    As you would expect, C++ provides a more fundamental and robust mechanism than Visual Basic for interprocess checking.

    The object you need for this situation is a named mutex. It is a system-wide object that can be locked and unlocked, to co-ordinate access to resources between processes.

    In this example, we create and lock a mutex when the application begins running. If the mutex already is locked, the creation fails and we close the application.

    This indicates another instance of the program is running, because the operating system unlocks the mutex if the process that locked it terminates for any reason.

    // MyApp.cpp : Defines the class behaviors for the application.
    //
    
    #include "stdafx.h"
    ...
    #include <afxmt.h>		// for CMutex
    ...
    
    BOOL CMyApp::InitInstance()
    {
    	CMutex Mutex(true,"MyApp_Mutex");
    	if (! Mutex.Lock(1000)) {
    		// Another instance is running, quit
    		Beep(15000,2000);
    		return FALSE;
    	}
            ...
    }
    

    Because you can name the mutex, this has an advantage over Visual Basic's PrevInstance property. The processes do not have to be running the same program in order to detect each other.

    Mutexes can also be used to co-ordinate access to any resource between processes and/or threads.

    If you wish to explicitly unlock the mutex, it is a good idea to create a CMutex, or CMutex pointer as a member variable.

    In MyApp.h:
    	CMutex *m_Mutex;
    
    In CMyApp::InitInstance():
    	CMutex Mutex(true,"MyApp_Mutex");
    	m_Mutex = &Mutex;
    	if (! Mutex.Lock(1000)) {
    		// Another instance is running, quit
    		Beep(15000,2000);
    		return FALSE;
    	}
    
    When you want to release the lock:
    	(CMyApp *) AfxGetApp())->m_Mutex->Unlock();