How to limit 32-bit applications to one instance in Visual C++ (243953)



The information in this article applies to:

  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET (2003)
  • Microsoft Visual C++ .NET (2002)
  • Microsoft Visual C++, 32-bit Professional Edition 6.0
  • Microsoft Visual C++, 32-bit Enterprise Edition 6.0
  • Microsoft Visual C++, 32-bit Learning Edition 6.0
  • Microsoft Visual C++, 32-bit Professional Edition 5.0
  • Microsoft Visual C++, 32-bit Enterprise Edition 5.0
  • Microsoft Visual C++, 32-bit Professional Edition 4.2
  • Microsoft Visual C++, 32-bit Enterprise Edition 4.2
  • Microsoft Visual C++ 4.1
  • Microsoft Visual C++ 4.0

This article was previously published under Q243953
Note Microsoft Visual C++ 2005, Microsoft Visual C++ .NET 2003, and Microsoft Visual C++ .NET 2002 support both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code.

SUMMARY

This article discusses how to limit an application to one instance. The method that is used in this article does not rely on any creation of windows. Therefore, the method can be used to limit an application to one instance that is developed in Visual C++. This includes console applications, WinCE applications, dialog box based applications, applications without a graphical user interface, and other applications.

MORE INFORMATION

The method that is used in this article is the one that is described in MSDN under the WinMain topic. It uses the CreateMutex function to create a named mutex that can be checked across processes. Instead of duplicating the same code for every application that you will use as a single instance, the code that you must have is in a C++ wrapper class that you can reuse across each application.

To use this functionality, follow these steps:
  1. Create a new header file with the name LimitSingleInstance.h, and then add it to your project.
  2. Copy the following code to the LimitSingleInstance.h file, and then save the file:
    #ifndef LimitSingleInstance_H
    #define LimitSingleInstance_H
    
    #include <windows.h> 
    
    //This code is from Q243953 in case you lose the article and wonder
    //where this code came from.
    class CLimitSingleInstance
    {
    protected:
      DWORD  m_dwLastError;
      HANDLE m_hMutex;
    
    public:
      CLimitSingleInstance(TCHAR *strMutexName)
      {
        //Make sure that you use a name that is unique for this application otherwise
        //two apps may think they are the same if they are using same name for
        //3rd parm to CreateMutex
        m_hMutex = CreateMutex(NULL, FALSE, strMutexName); //do early
        m_dwLastError = GetLastError(); //save for use later...
      }
       
      ~CLimitSingleInstance() 
      {
        if (m_hMutex)  //Do not forget to close handles.
        {
           CloseHandle(m_hMutex); //Do as late as possible.
           m_hMutex = NULL; //Good habit to be in.
        }
      }
    
      BOOL IsAnotherInstanceRunning() 
      {
        return (ERROR_ALREADY_EXISTS == m_dwLastError);
      }
    };
    #endif
    					
    Note In Visual C++ 2005, you must add the common language runtime support compiler option (/clr:oldSyntax) to successfully compile the previous code sample. To add the common language runtime support compiler option, follow these steps:
    1. Click Project, and then click ProjectName Properties.

      Note ProjectName is a placeholder for the name of the project.
    2. Expand Configuration Properties, and then click General.
    3. In the right pane, click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project settings.
    4. Click Apply, and then click OK.
    For more information about the common language runtime support compiler options, visit the following Microsoft Developer Network (MSDN) Web site:
  3. #include the LimitSingleInstance.h file where the entry point of the program is located. If this is to be used in an MFC Application, it is the file where the InitInstance() function for the application is located. In a Win32 SDK application, it is where the WinMain() function is located. In a console application, it is where the main() function is located.
    #include "LimitSingleInstance.H"
    					
  4. Create a global instance of the CLimitSingleInstance class before the entry point function. If this is being used in a MFC application, create the instance before the InitInstance() function.
  5. Pass a unique name to the constructor of the global CLimitSingleInstance instance. It is recommended that you use a unique name so another application that may be using this article will not conflict when doing the duplicate checking. An easy way to get a unique name that no one else will have is to use the GUIDGEN tool. To access the tool, click Start, click Run, and then type GUIDGEN. If for some reason you do not have the tool, the tool is provided as a sample in MSDN. Type GUIDGEN in the MSDN index to find it. Make sure that you use the Registry Format option in the GUIDGEN tool.
    #include "LimitSingleInstance.H"
    
    // The one and only CLimitSingleInstance object.
    // Change what is passed to constructor. GUIDGEN Tool may be of help.
    CLimitSingleInstance g_SingleInstanceObj(TEXT("Global\\{719967F0-DCC6-49b5-9C61-DE91175C3187}"));
    					
  6. In your entry point function, call the IsAnotherInstanceRunning() method on the global instance of the CLimitSingleInstance class and check the return value. If the function returns TRUE, return from the entry point function. Otherwise, continue execution as normal.

    In an MFC Application, you can do something similar to the following:
    #include "LimitSingleInstance.H"
    
    // The one and only CLimitSingleInstance object.
    CLimitSingleInstance g_SingleInstanceObj(TEXT("Global\\{05CA3573-B449-4e0b-83F5-7FD612E378E9}"));
    
    BOOL CSingleInstDlg5App::InitInstance()
    {
        if (g_SingleInstanceObj.IsAnotherInstanceRunning())
           return FALSE; 
    
    //Rest of code.
    }
    						
    In a Console Application, you can do something similar to the following:
    #include "LimitSingleInstance.H"
    
    // The one and only CLimitSingleInstance object.
    CLimitSingleInstance g_SingleInstanceObj(TEXT("Global\\{9DA0BEED-7248-450a-B27C-C0409BDC377D}"));
    
    int main(int argc, char* argv[])
    {
        if (g_SingleInstanceObj.IsAnotherInstanceRunning())
           return 0;
    //Rest of code.
    }
    						
    In a Win32 SDK Application, you can do something similar the following:
    #include "LimitSingleInstance.H"
    
    // The one and only CLimitSingleInstance object.
    CLimitSingleInstance g_SingleInstanceObj(TEXT("Global\\{2194ABA1-BFFA-4e6b-8C26-D191BB16F9E6}"));
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int cmdShow)
    {
        if (g_SingleInstanceObj.IsAnotherInstanceRunning())
           return FALSE; 
    //Rest of code.
    }
    						
After following these steps, the application will not allow more than one instance to remain active at the same time.

Note When running under Terminal Services, not adding Global\ will guarantee one instance per Terminal Services session.
   CLimitSingleInstance g_SingleInstanceObj(TEXT("{719967F0-DCC6-49b5-9C61-DE91175C3187}"));
					
Adding "Global\" will guarantee that there is only one instance of the application on a computer. This applies whether Terminal Services is running or not.

REFERENCES

For more information, click the following article number to view the article in the Microsoft Knowledge Base:

238100 How to limit 32-bit MFC SDI applications to a single instance on WinCE


Modification Type:MajorLast Reviewed:1/9/2006
Keywords:kbinfo kbhowto KbUIDesign KB243953 kbAudDeveloper