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
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.
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();