locked
How to Run only one instance of MFC application?? RRS feed

  • Question

  • Hi,

    I am using Visual Studio 2008. I made a Dialog based MFC Application. I want that Only one instance of my application should open at a time. When User try to open another instance it should display a message or bring forward the already running application. 

    How Can I do this??

    Regards,

    Thursday, January 20, 2011 6:56 AM

Answers

  • You can use i.e. "CreateMutex" to find out if your app is currently running. If your application is running the 2nd application gets an error creating the same mutex since it is created. Therefore you know the app is running and you terminate the 2nd instance.

    Here a sample code piece:

    In your CWinApp Class header
    class CYourAppclass::CWinApp
    {
    ...
    HANDLE m_Mutex_h;
    UINT m_WinMsg_ui; 
    ...
    }
    In your CWinApp CPP:
    BOOL CYourAppclass::InitInstance()
    {
    m_WinMsg_ui=RegisterWindowMessage(_T("ONNMESSAGE"));
    m_Mutex_h=::CreateMutex(NULL, FALSE, STR_VIEWUTILITYMUTEX);
    if ((m_Mutex_h!=NULL)&&(GetLastError()!=ERROR_ALREADY_EXISTS))
    {
    // App is NOT running twice
    CYourDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    }
    else
    {
    // App is running twice send message to running app, the app will now know a 2nd instance was started
    ::SendMessage(HWND_BROADCAST, m_WinMsg_ui, 0, 0); 
    }

    The "SendMessage" is only needed if you want that the running application knows a 2nd instance was started. You send a registered windows message to your running application, and your running application will receive this message and knows that a 2nd instance was started. You can create i.e. code in your message handler to bring your app to the front.

    • Edited by Bordon Thursday, January 20, 2011 7:17 AM
    • Marked as answer by Sarfraz07 Thursday, January 20, 2011 9:27 AM
    Thursday, January 20, 2011 7:01 AM
  • Try this:

    m_hOneInstanceMutex = CreateMutex(NULL, TRUE, _T("Hello"));
    if ((m_hOneInstanceMutex!=NULL)&&(GetLastError()!=ERROR_ALREADY_EXISTS))
    {
    }
    else
    { 
    ::MessageBox(NULL, _T("An Instance of this application is already running..."), _T(""), MB_OK);
    return FALSE; 
    }

     

    • Marked as answer by Sarfraz07 Thursday, January 20, 2011 9:27 AM
    Thursday, January 20, 2011 7:23 AM
  • The code looks like, you must create your dialog only if you have one instance running. I marked the part bold:

    BOOL CYourAppclass::InitInstance()
    {
    m_WinMsg_ui=RegisterWindowMessage(_T("ONNMESSAGE"));
    m_Mutex_h=::CreateMutex(NULL, FALSE, STR_VIEWUTILITYMUTEX);
    if ((m_Mutex_h!=NULL)&&(GetLastError()!=ERROR_ALREADY_EXISTS))
    {
    // App is NOT running twice
    CYourDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    }
    else
    {
    // App is running twice send message to running app, the app will now know a 2nd instance was started
    ::SendMessage(HWND_BROADCAST, m_WinMsg_ui, 0, 0);
    }

    • Marked as answer by Sarfraz07 Thursday, January 20, 2011 9:27 AM
    Thursday, January 20, 2011 9:00 AM

All replies

  • You can use i.e. "CreateMutex" to find out if your app is currently running. If your application is running the 2nd application gets an error creating the same mutex since it is created. Therefore you know the app is running and you terminate the 2nd instance.

    Here a sample code piece:

    In your CWinApp Class header
    class CYourAppclass::CWinApp
    {
    ...
    HANDLE m_Mutex_h;
    UINT m_WinMsg_ui; 
    ...
    }
    In your CWinApp CPP:
    BOOL CYourAppclass::InitInstance()
    {
    m_WinMsg_ui=RegisterWindowMessage(_T("ONNMESSAGE"));
    m_Mutex_h=::CreateMutex(NULL, FALSE, STR_VIEWUTILITYMUTEX);
    if ((m_Mutex_h!=NULL)&&(GetLastError()!=ERROR_ALREADY_EXISTS))
    {
    // App is NOT running twice
    CYourDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    }
    else
    {
    // App is running twice send message to running app, the app will now know a 2nd instance was started
    ::SendMessage(HWND_BROADCAST, m_WinMsg_ui, 0, 0); 
    }

    The "SendMessage" is only needed if you want that the running application knows a 2nd instance was started. You send a registered windows message to your running application, and your running application will receive this message and knows that a 2nd instance was started. You can create i.e. code in your message handler to bring your app to the front.

    • Edited by Bordon Thursday, January 20, 2011 7:17 AM
    • Marked as answer by Sarfraz07 Thursday, January 20, 2011 9:27 AM
    Thursday, January 20, 2011 7:01 AM
  • I did something like this, but it is not working.

     

    HANDLE m_hOneInstanceMutex = NULL;

      m_hOneInstanceMutex = CreateMutex(NULL, TRUE, "Hello");

      if(m_hOneInstanceMutex == NULL)

      {    

          MessageBoxA("An Instance of this application is already running...");

          return FALSE;    

      }

     

    I wrote above code in OnInitDialog() function. But this does not show a message box and let the application to run multiple instances.

    Thursday, January 20, 2011 7:12 AM
  • Try this:

    m_hOneInstanceMutex = CreateMutex(NULL, TRUE, _T("Hello"));
    if ((m_hOneInstanceMutex!=NULL)&&(GetLastError()!=ERROR_ALREADY_EXISTS))
    {
    }
    else
    { 
    ::MessageBox(NULL, _T("An Instance of this application is already running..."), _T(""), MB_OK);
    return FALSE; 
    }

     

    • Marked as answer by Sarfraz07 Thursday, January 20, 2011 9:27 AM
    Thursday, January 20, 2011 7:23 AM
  • Thanks Sir,

    I replaced my code with your. It shows the message box that an instance is already running. But when I close that message box it show another instance of application. Am I writing the code in correct location. I am writing this code in OnInitDialog() function. My application is Dialog based MFC application. My dlg class is inherited from CDialog class.

    Thursday, January 20, 2011 7:39 AM
  • The code looks like, you must create your dialog only if you have one instance running. I marked the part bold:

    BOOL CYourAppclass::InitInstance()
    {
    m_WinMsg_ui=RegisterWindowMessage(_T("ONNMESSAGE"));
    m_Mutex_h=::CreateMutex(NULL, FALSE, STR_VIEWUTILITYMUTEX);
    if ((m_Mutex_h!=NULL)&&(GetLastError()!=ERROR_ALREADY_EXISTS))
    {
    // App is NOT running twice
    CYourDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    }
    else
    {
    // App is running twice send message to running app, the app will now know a 2nd instance was started
    ::SendMessage(HWND_BROADCAST, m_WinMsg_ui, 0, 0);
    }

    • Marked as answer by Sarfraz07 Thursday, January 20, 2011 9:27 AM
    Thursday, January 20, 2011 9:00 AM
  • I do this.

    in APP.cpp

    // this prevents more than one instance of the application from running
    // use this linker option /SECTION:.control_seg,RWSE
    #pragma data_seg(push, vermin_ctrl, ".control_seg")
    int  nAlreadyRunning              = 0 ;
    char szPreviousClassName[128]     = _T("") ;
    int  cbPreviousClassName          = sizeof( szPreviousClassName );
    char szOpenDocumentPath[MAX_PATH] = "";
    #pragma data_seg(pop, vermin_ctrl)

    ...

    BOOL CVerminApp::InitInstance()
    {
        AfxInitRichEdit2();
       
        // Parse command line for standard shell commands, DDE, file open
        CCommandLineInfo cmdInfo;
        ParseCommandLine(cmdInfo);

        if(nAlreadyRunning)
        {  
            CWnd *pWnd = CWnd::FindWindow(szPreviousClassName, NULL) ;
            if(NULL != pWnd)
            {  
                pWnd->BringWindowToTop() ;
                if(pWnd->IsIconic())
                {
                    pWnd->ShowWindow(SW_RESTORE) ;
                }
                if( cmdInfo.m_nShellCommand == CCommandLineInfo::FileOpen )
                {
                    strcpy_s( szOpenDocumentPath, sizeof( szOpenDocumentPath ), cmdInfo.m_strFileName );
                    LPARAM lParam = reinterpret_cast< LPARAM >( szOpenDocumentPath );
                    pWnd->SendMessage( ID_OPEN_DOCUMENT_FILE, 0, lParam );
                }
            }
            return FALSE ;
        }
        else
        {   nAlreadyRunning = 1 ;
        }

    ...

    }

     

    In MainFrame.cpp

    extern char szPreviousClassName[] ;
    extern int  cbPreviousClassName;

    BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
    {
        if(NULL != cs.lpszClass)
          { strcpy_s(szPreviousClassName, cbPreviousClassName, cs.lpszClass) ;
          }
    ...

    }

     

    I find this works quite well

    Friday, February 18, 2011 4:11 PM
  • Hi,
     
    I am using Visual Studio 2008. I made a Dialog based MFC Application. I want that Only one instance of my application should open at a time. When User try to open another instance it should display a message or bring forward the already running application.
     
    How Can I do this??
    I use the code from MVP Joe Newcomer's site:
     
    http://www.flounder.com/nomultiples.htm
     

    David Wilkinson | Visual C++ MVP
    Friday, February 18, 2011 4:25 PM