Look at the Microsoft sample ONETIME.EXE, (MSDN CD or ftp.microsoft.com).
In Brief:
- const char* MyMainWndClassName = "MyMainWndXQW"
BOOL CMyApp::InitApplication()
{
//Call base class. Default version does nothing.
CWinApp::InitApplication();
- WNDCLASS wndcls;
- // start with NULL defaults
memset(&wndcls, 0, sizeof(WNDCLASS));
- // Get class information for default
window class.
::GetClassInfo(AfxGetInstanceHandle(),"AfxFrameOrView",&wndcls);
- // Substitute unique class name for new
class
wndcls.lpszClassName = MyMainWndClassName;
- //Register new class and return the
result code
return ::RegisterClass(&wndcls);
}
And:
- BOOL CMyApp::FirstInstance()
{
CWnd *PrevCWnd, *ChildCWnd;
- // Determine if another window with our
class name exists...
PrevCWnd = CWnd::FindWindow(MyMainWndClassName, NULL);
if (PrevCWnd != NULL)
{
- // if so, does it
have any popups?
ChildCWnd=PrevCWnd->GetLastActivePopup();
- // Bring the main
window to the top
PrevCWnd->BringWindowToTop();
- // If iconic,
restore the main window
if (PrevCWnd->IsIconic())
PrevCWnd->ShowWindow(SW_RESTORE);
- // If there
are popups, bring them along too!
if (PrevCWnd != ChildCWnd)
ChildCWnd->BringWindowToTop();
- // Return FALSE.
This isn't the first instance
// and we are done activating the previous one.
return FALSE;
}
else
// First instance. Proceed as normal.
return TRUE;
}
- CMyApp::InitInstance()
{
- if (!FirstInstance())
return FALSE;
//...
}
Niels Ull Jacobsen (null@diku.dk), programmer.tools, 6/19/95
See also MS Knowledge base article Q124134 ( "Allowing Only One Application
Instance on Win32s") and Advanced Windows NT , chapter 7, "Prohibiting Multiple
Instances of an Application from Running: The MultInst Sample Application" (available
on the MSDN).
Niels Ull Jacobsen (null@diku.dk), email, 8/8/95
- update - these were posted to mfc-l:
I have each InitApplication() create a semaphore. If GetLastError() returns
ERROR_ALREADY_EXISTS then I know that some other application is already running and has
gotten that far so I bail.
- Yourapp::InitInstance()
- {
- hMutexOneInstance =
CreateMutex(NULL,TRUE,_T("PreventSecondInstance"));
- if(GetLastError() ==
ERROR_ALREADY_EXISTS)
- bFound = TRUE;
- if(hMutexOneInstance)
-
ReleaseMutex(hMutexOneInstance);
- return (bFound == TRUE) ? FALSE : TRUE;
- }
mcontest@universal.com
There is a nice section in Jeffrey Richter's book Advanced Windows NT about this.
Essentially, it uses shared data segments between processes.
- Step1:
- =======
- In your main file, add:
#pragma data_seg(".SharedData")
LONG nUsageCount = -1;
#pragma data_seg()
-
- Step 2 :
- =======
- In your Application's InitInstance(), call:
- InterlockedIncrement ( &nUsageCount );
-
- This function returns the incremented value of the variable. If it is non-zero, you know
that you are not the first App.
- In your Application's ExitInstance() call:
- InterlockedDecrement( &nUsageCount );
-
- Step3:
- =======
- In your DEF file, have the following lines: ( Note that the segment name you give here
should match the one in the application's main file. )
- SEGMENTS
- .SharedData shared
abalakri@us.oracle.com
You'd better use one of the built-in synchronization methods. See Q124134 : Allowing
Only One Application Instance on Win32s for a sample of using a memory mapped file for
synchronization. It doesn't include starting the previous instance, but if you detect that
you're not the only one running, it should be pretty simple: if CreateFileMapping fails,
try to find the previous instance from the window class name. If it's not found, sleep for
a while and start over (with CreateFileMapping). In this way, either you will find
the other instance when it gets around to creating it's window or CreateFileMapping will
eventually succeed. The advantage of using CreateFileMapping instead of CreateObject is
that it also works on Win32s.
- - nuj@kruger.dk
Note: There's a sample of this that was contributed by john@jing.com (John Xu)
called onetime4.zip that is in the MFC FAQ archive (see section 2.2.6 for MFC FAQ archive
details).