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

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • With the average hard drive now averaging one terabyte in size, the fallout from the explosion of user-created data has become an overwhelming volume of potential evidence that law-enforcement and corporate investigators spend countless hours examining. Join Us and SANS' Rob Lee for our 45-minute webinar, A Triage and Collection Strategy for Time-Sensitive Investigations, will demonstrate how to: Identify the folders and files that often contain key insights Reduce the time spent sifting through content by …

Most Popular Programming Stories

More for Developers

RSS Feeds