Click to search the site Click to log in
Online articles
Download free tools
Support pages, per product
Services
Frequently asked questions, per product
Limiting an application to one instance
Author: George Mihaescu
Published: September 18, 2001
Category: Implementation technique / Win32
Notes:
Description: This article presents a technique that I've been using for many years for limiting a Win32 application to a single instance, with the additional feature of activating the existing instance if already running. This technique works on all Win32 platforms (98 / ME / NT / 2000 / XP / Vista).
View count: 1,973
Comments: 1 Read comments or post your own

  Print viewOpens in new window
 Limiting an application to one instance

Limiting an application to one instance

 

By George Mihaescu

 

Summary: this article presents a technique that I've been using for many years for limiting a Win32 application to a single instance, with the additional feature of activating the existing instance if already running. This technique works on all Win32 platforms (98 / ME / NT / 2000 / XP / Vista).

The problem

You have a Win32 application that you want to limit to a single instance. Additionally, if the application is a GUI and there is already an instance running, you may want to activate the running instance (because, for example, the user may not be aware that an instance is already running and attempts to start a new one simply because he did not see the running one).

The solution

My solution is based on the uniqueness of the names of Win32 kernel objects. The code below uses a semaphore for this purpose, but you may choose to use a different kernel object if you prefer.

 

To implement this solution, simply add the following at the start of your program (the example is in an MFC app, but you can do the same in any Win32 application):

 

///////////////////////////////////////////////////////////////////////// Name of the semaphore used to control the number of instances

// running

LPCTSTR INSTANCE_DETECTION_OBJECT_NAME = _T("www.abstraction.net_OneInstanceApp_v10_InstanceControl");

 

BOOL COneInstanceApp::InitInstance()

{

      // check whether we have already an instance running. If so,

//pass control to that

      HANDLE h_sem = ::CreateSemaphore (NULL, 0, 1,

                                    INSTANCE_DETECTION_OBJECT_NAME);

      DWORD err = ::GetLastError ();

      if (err == ERROR_ALREADY_EXISTS)

      {

            //object exists already, must have been created by

//a previous instance, end this new instance

            return FALSE;

      }

 

      //The rest of the code that initializes your application

      ...

     

}

 

The only thing to pay attention to is the name of the kernel object; create a name that is unlikely to clash with another object of that type (for instance, prefix it with you domain name, then continue with the application name – and you may want to consider including the version as well, so that in subsequent versions of the program you can change the "one instance" rule – for example, allow only one instance of version 1.0, but also allow side-by-side another instance of 2.0, but not multiples of each version).

 

Now, if the application is GUI-based, it is a nice touch to also activate the existing running instance; in order to do this, you need to add a shared section of memory to you application – this shared memory will store the handle of the main window of the running instance, so that subsequent instances will find it there and activate it. The Visual C++ linker allows creating a shared section of memory in a program in a very simple manner, through the use of the #pragma data_seg directive. This is how the code above looks like with the addition of this feature:

 

///////////////////////////////////////////////////////////////////////// Name of the semaphore used to control the number of instances

// running

LPCTSTR INSTANCE_DETECTION_OBJECT_NAME = _T("www.abstraction.net_OneInstanceApp_v10_InstanceControl");

 

//this piece of data is shared by all instances, so that when

//detecting that we have another instance running, we can use

//this to activate the window of that first instance:

#pragma data_seg ("InstanceControl")

LONG  g_first_instance_main_hwnd          =     0;

#pragma data_seg ()

 

#pragma comment (linker, "/SECTION:InstanceControl,RWS")

 

BOOL COneInstanceApp::InitInstance()

{

      // check whether we have already an instance running.

//If so, pass control to that

      HANDLE h_sem = ::CreateSemaphore (NULL, 0, 1,

                                    INSTANCE_DETECTION_OBJECT_NAME);

      DWORD err = ::GetLastError ();

      if (err == ERROR_ALREADY_EXISTS)

      {

            //object exists already, must have been created by

//a previous instance, activate that

            //(we should have the handle of its main window in

//the shared data area).

            ASSERT (g_first_instance_main_hwnd != 0);

 

            if (::IsWindow ((HWND) g_first_instance_main_hwnd))

            {

                  //first attempt to restore (in case it's minimized)

                  ::ShowWindow ((HWND) g_first_instance_main_hwnd,

                                    SW_SHOWNORMAL);

                  //then bring to top

                  ::SetForegroundWindow ((HWND)

                                          g_first_instance_main_hwnd);

            }

 

            //end this new instance

            return FALSE;

      }

 

      // The rest of your code here, etc

      ...

 

      // The one and only window has been initialized, so show

//and update it

      m_pMainWnd->ShowWindow(SW_SHOW);

      m_pMainWnd->UpdateWindow();

 

      //at this point, since we got here, we must be the very

//first instance (and the only one allowed

      //to run) so initialize the shared data segment with the

//main window handle

      g_first_instance_main_hwnd =

(LONG) (m_pMainWnd -> GetSafeHwnd ());

 

      return TRUE;

}

 

As I'm writing this article, it just crossed my mind that a possible alternative to using a shared section of memory would be using a memory mapped file as the named object that flags that an instance is already running, and if present, look into the mapped file (by mapping a view of it) and read from it the handle of the main window of that running instance. This solution covers both the control of number of instances and the sharing of the main window handle through a single mechanism, the memory mapped file. Should work without a problem – so that's a possible choice in case you are not using Visual C++ for development and your linker does not allow you to set up a shared memory section as above.

 


Reader comments:
Name: (optional)
Verification text:    
(type as in image next to it)
Comment: max 2,000 characters; for security reasons no active content / no HTML formatting is supported.
Please stick to the subject of the article; comments are reviewed and unrelated / inappropriate ones will be deleted.

On Jun 18, 2009 at 14:54 EST Anonymous said:

Thanks for this article, BUT: 1- the data_seg pragma did not work. 2- using the IsWindow on another process's window handle does now work Is your application working on your machine?
Copyright 2308 registered users, 20 users online now