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

posted Oct 19, 2015, 4:54 AM by Javad Taghia

https://support.microsoft.com/en-us/kb/243953

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:

Create a new header file with the name LimitSingleInstance.h, and then add it to your project.

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:

Click Project, and then click ProjectName Properties.

Note ProjectName is a placeholder for the name of the project.

Expand Configuration Properties, and then click General.

In the right pane, click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project settings.

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:

#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"

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.

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}"));

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.