Single application instance
-
Does anyone know of a simple way to ensure that an application has only a single instance running? When the app is clicked again the running instance should be restored and activated. I am doing all this now with an event and a background thread. It works fine but I seem to recall that there is a simpler way of doing this and I can't find it anywhere. Apropos, is it possible to send a windows message, like WM_SHOWWINDOW, between applications rather than within an application? By the way I have no problem getting the PID or the window handle if they are needed for the solution. Have Fun all.
-
Does anyone know of a simple way to ensure that an application has only a single instance running? When the app is clicked again the running instance should be restored and activated. I am doing all this now with an event and a background thread. It works fine but I seem to recall that there is a simpler way of doing this and I can't find it anywhere. Apropos, is it possible to send a windows message, like WM_SHOWWINDOW, between applications rather than within an application? By the way I have no problem getting the PID or the window handle if they are needed for the solution. Have Fun all.
Re Q1: In 16 bit windows, which was an 'all one process' affair, you could check the hInstance param passed to the entry fn to do this. Nowadays, the de jure standard is to use shared memory - a named memory mapped file (see
CreateFileMapping
andMapViewOfFile
) that the app creates on startup - if it already exists, exit, perhaps passing control to the first instance. There was an excellent intro to this stuff in Jeff Prosise's Wicked Code MSJ November 1998. A background thread approach sounds interesting though. -
Does anyone know of a simple way to ensure that an application has only a single instance running? When the app is clicked again the running instance should be restored and activated. I am doing all this now with an event and a background thread. It works fine but I seem to recall that there is a simpler way of doing this and I can't find it anywhere. Apropos, is it possible to send a windows message, like WM_SHOWWINDOW, between applications rather than within an application? By the way I have no problem getting the PID or the window handle if they are needed for the solution. Have Fun all.
and remember we went through the mutex idea here a whiles ago --- "every year we invent better idiot proof systems and every year they invent better idiots"
-
Does anyone know of a simple way to ensure that an application has only a single instance running? When the app is clicked again the running instance should be restored and activated. I am doing all this now with an event and a background thread. It works fine but I seem to recall that there is a simpler way of doing this and I can't find it anywhere. Apropos, is it possible to send a windows message, like WM_SHOWWINDOW, between applications rather than within an application? By the way I have no problem getting the PID or the window handle if they are needed for the solution. Have Fun all.
This is the way I've done it for about 100 years now, works like a charm : // Global declaration in CWinApp: LPCTSTR lpszUniqueClass = _T("MyUnigueClassName"); CMyWinApp::OnInitInstance() { // Check status of class name... if( DoIExist()) { return( FALSE ); } . . . // Register our unique class name that we wish to use WNDCLASS wndcls; . . . // Specify our own class name for using FindWindow later wndcls.lpszClassName = lpszUniqueClass; // Register new class and exit if it fails if(!AfxRegisterClass(&wndcls)) { TRACE("Class Registration Failed\n"); return FALSE; } . . . } BOOL CMyWinApp::DoIExist() { CWnd *pWndPrev, *pWndChild; if(( pWndPrev = CWnd::FindWindow(lpszUniqueClass, NULL ) )) { if( pWndPrev->IsIconic() ) { // If iconic, restore the main window pWndPrev->ShowWindow(SW_RESTORE); } // if alive, does it have any popups? if(( pWndChild = pWndPrev->GetLastActivePopup()) != NULL ) { pWndChild->SetForegroundWindow(); } return TRUE; } return FALSE; }
-
Does anyone know of a simple way to ensure that an application has only a single instance running? When the app is clicked again the running instance should be restored and activated. I am doing all this now with an event and a background thread. It works fine but I seem to recall that there is a simpler way of doing this and I can't find it anywhere. Apropos, is it possible to send a windows message, like WM_SHOWWINDOW, between applications rather than within an application? By the way I have no problem getting the PID or the window handle if they are needed for the solution. Have Fun all.
Great ideas but just as much work as my original. Pity that hInstance is not atomic across multi-cpu systems but that's asking a lot. Here is my solution for anyone who is interested. I don't think its very elegant but it works. At the beginning of xxxApp::InitInstance()look for an event. BOOL CTestApp::InitInstance() { // See if an instance of myself is already running if (( eDoIExist = OpenEvent( EVENT_ALL_ACCESS, NULL, "YesIExist" )) != NULL ) { // Yes. There is someone out there. Wake it up. SetEvent( eDoIExist ); // And get out return FALSE; } // No. I am the first so set up an event. eDoIExist = CreateEvent( NULL, TRUE, FALSE, "YesIExist" ); ..... Later in the init code when the main window (in my case a dialog) is ..... set up CTestDlg dlg; m_pMainWnd = &dlg; // Create a background thread to look for any other instance and send it // the main window ::CreateThread( NULL, 0, LookForMyself, m_pMainWnd , 0, NULL ); ..... At the end of the same source DWORD WINAPI LookForMyself( LPVOID lpParameter ) { // Forever do { WaitForSingleObject( eDoIExist, INFINITE ); // This is just a little flashy way of re-activating the running // instance ((CDialog *)lpParameter)->ShowWindow( SW_SHOWMINIMIZED ); ((CDialog *)lpParameter)->ShowWindow( SW_RESTORE ); // Reset and wait for more intruders ResetEvent( eDoIExist ); } while ( TRUE ); return 0; } Thank you all for your responses!
-
Great ideas but just as much work as my original. Pity that hInstance is not atomic across multi-cpu systems but that's asking a lot. Here is my solution for anyone who is interested. I don't think its very elegant but it works. At the beginning of xxxApp::InitInstance()look for an event. BOOL CTestApp::InitInstance() { // See if an instance of myself is already running if (( eDoIExist = OpenEvent( EVENT_ALL_ACCESS, NULL, "YesIExist" )) != NULL ) { // Yes. There is someone out there. Wake it up. SetEvent( eDoIExist ); // And get out return FALSE; } // No. I am the first so set up an event. eDoIExist = CreateEvent( NULL, TRUE, FALSE, "YesIExist" ); ..... Later in the init code when the main window (in my case a dialog) is ..... set up CTestDlg dlg; m_pMainWnd = &dlg; // Create a background thread to look for any other instance and send it // the main window ::CreateThread( NULL, 0, LookForMyself, m_pMainWnd , 0, NULL ); ..... At the end of the same source DWORD WINAPI LookForMyself( LPVOID lpParameter ) { // Forever do { WaitForSingleObject( eDoIExist, INFINITE ); // This is just a little flashy way of re-activating the running // instance ((CDialog *)lpParameter)->ShowWindow( SW_SHOWMINIMIZED ); ((CDialog *)lpParameter)->ShowWindow( SW_RESTORE ); // Reset and wait for more intruders ResetEvent( eDoIExist ); } while ( TRUE ); return 0; } Thank you all for your responses!
-
You could use a mutex to check if you are the first instance, and if not send a app specific message with BroadcastSystemMessage(). (never actually tried it, but i think it should work and be quite a simple solution)
-
Maybe the mutex is not even needed, sending the app specific message with BroadcastSystemMessage() and the flag BSF_QUERY and checking the retval might do the trick.
-
Does anyone know of a simple way to ensure that an application has only a single instance running? When the app is clicked again the running instance should be restored and activated. I am doing all this now with an event and a background thread. It works fine but I seem to recall that there is a simpler way of doing this and I can't find it anywhere. Apropos, is it possible to send a windows message, like WM_SHOWWINDOW, between applications rather than within an application? By the way I have no problem getting the PID or the window handle if they are needed for the solution. Have Fun all.
If you have a custom mainframe class (RegisterWndClass()) you can just do a FindWindow(clasname, window caption) and then send a message to the HWND that gets returned. Bret Faller Odyssey Computing, Inc.
-
This is the way I've done it for about 100 years now, works like a charm : // Global declaration in CWinApp: LPCTSTR lpszUniqueClass = _T("MyUnigueClassName"); CMyWinApp::OnInitInstance() { // Check status of class name... if( DoIExist()) { return( FALSE ); } . . . // Register our unique class name that we wish to use WNDCLASS wndcls; . . . // Specify our own class name for using FindWindow later wndcls.lpszClassName = lpszUniqueClass; // Register new class and exit if it fails if(!AfxRegisterClass(&wndcls)) { TRACE("Class Registration Failed\n"); return FALSE; } . . . } BOOL CMyWinApp::DoIExist() { CWnd *pWndPrev, *pWndChild; if(( pWndPrev = CWnd::FindWindow(lpszUniqueClass, NULL ) )) { if( pWndPrev->IsIconic() ) { // If iconic, restore the main window pWndPrev->ShowWindow(SW_RESTORE); } // if alive, does it have any popups? if(( pWndChild = pWndPrev->GetLastActivePopup()) != NULL ) { pWndChild->SetForegroundWindow(); } return TRUE; } return FALSE; }
-
Hi! I tried your example, but failed to get the result. the AfxRegisterClass() always returns false. DO you know why? I use appWizard to make my dialog base application Thank You very much Vu vucsuf
This is where the answer is: http://support.microsoft.com/default.aspx?scid=kb;EN-US;q243953 I found this out after failing to ask for help on this forum. I guess there are more than 1 way to do it. It just happened to me that all the solutions provided by this forum does not work for me at all. Vu http://support.microsoft.com/default.aspx?scid=kb;EN-US;q243953 vucsuf