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

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • QA teams don't have time to test everything yet they can't afford to ship buggy code. Learn how Coverity can help organizations shrink their testing cycles and reduce regression risk by focusing their manual and automated testing based on the impact of change.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds