Simple Single Instance Windows

Limiting an application to a single instance is very problematic. There are dozens of solutions available; most of them work most of the time. The problem is that solutions that use ProcessIDs or Window Handles fail occasionally due to Windows sloppy internal handling.

Here is a quick and dirty solution for keeping a single instance of a window. It uses shared memory to maintain a linked list of open windows. An application checks the list on startup, and if the application is on the list, it is exited.

Here is the header:

#if !defined(AFX_SingleInstance_H__INCLUDED_)
#define AFX_SingleInstance_H__INCLUDED_

// SingleInstance.h : header file
//

void RegisterSiblingWindowHandle(LPCTSTR lpLabel, HWND hWnd);
HWND GetSiblingWindowHandle(LPCTSTR lpLabel);
void RemoveSiblingWindowHandle(LPCTSTR lpLabel);
void RemoveSiblingWindowHandle(HWND hWnd);
void OpenSiblingWindowHandles(void);
void CloseSiblingWindowHandles(void);

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations
// immediately before the previous line.

#endif // !defined(AFX_SingleInstance_H__INCLUDED_)

To use the code, you need to activate the link to the shared list. The easiest way to do that is to insert the function

OpenSiblingWindowHandles();

into the constructor of CWinApp() if you are using MFC, or right after the RegisterClass() in your WinMain() in a standard Windows application.

You need to release the list at the end of the application as well with

CloseSiblingWindowHandles();

This works from the CWinApp() destructor in MFC or after the message loop in a Windows application.

When an application starts, before the main window is created (either via ProcessShellCommand(), DoModal(), or CreateWindow()), insert this code:

HWND hWndOther = GetSiblingWindowHandle(_T("My Unique ID"));
if( hWndOther != NULL )
{
   ::SetWindowPos(hWndOther, HWND_TOP, 0, 0, 0, 0,
                  SWP_NOMOVE|SWP_NOSIZE);
   ::SetFocus(hWndOther);
   return FALSE;
}

When a new window is opened (like in CMainFrame or after CreateWindow()):

RegisterSiblingWindowHandle(_T("My Unique ID"), m_hWnd);

To unregister a window (in ExitInstance() or just before the CloseSiblingWindowHandles()):

RemoveSiblingWindowHandle(_T("My Unique ID"));

Of course, replace all the _T("My Unique ID") tags with a unique ID for your app.



About the Author

Erik Gawtry

I have worked as a Software Engineer since 1985. I currently work with Windows, Unix/Linux, DSP, and Microcontrollers.

Downloads

Comments

  • killed processes ?

    Posted by fredwobus on 11/09/2005 04:27am

    How does this code deal with processes killed in the task manager ? Although your code looks interesting, you fail to mention what the problems with the other solutions are. Thanks

    • Re: Killed Processes

      Posted by egawtry on 11/09/2005 12:32pm

      The code deals with underegistered closed windows and processes by checking with the IsWindow() and automatically cleaning up.
      
      The primary problems with the two other common methods:
      
      Window Caption Text Lookup
      ==========================
      1. What if the window is hidden?  It doesn't appear in window lists.
      2. Maintaining the label as a constant is not attractive.
      3. Windows sometimes ignores windows - Windows has done this since Windows 3.0 (funny - 2.0 didn't have the problem).  This seems completely random.
      
      Searching for process ID
      ========================
      This is a bit more reliable that the caption text search, it fact it works 99.9% of the time.  This is what is the basis for many of the other routines here on CodeGuru.  It still falls prey to #3 mentioned under caption text searches.
      
      DDE
      ===
      This is reliable unless your DDE engine in Windows has crashed.  DDE is stable under Win9x, but seems to randomly crash under WinNT and Win2000.  I haven't tested it under WinXP (I gave up back with W2K).

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As mobile devices have pushed their way into the enterprise, they have brought cloud apps along with them. This app explosion means account passwords are multiplying, which exposes corporate data and leads to help desk calls from frustrated users. This paper will discover how IT can improve user productivity, gain visibility and control over SaaS and mobile apps, and stop password sprawl. Download this white paper to learn: How you can leverage your existing AD to manage app access. Key capabilities to …

  • Best-in-Class organizations execute on a strategy that supports the multi-channel nature of customer requests. These leading organizations do not just open up their service infrastructures to accommodate new channels, but also empower their teams to deliver an effective and consistent experience regardless of the channel selected by the customer. This document will highlight the key business capabilities that support a Best-in-Class customer engagement strategy.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds