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

  • 10 Rules that Make or Break Enterprise App Development Projects In today's app-driven world, application development is a top priority. Even so, 68% of enterprise application delivery projects fail. Designing and building applications that pay for themselves and adapt to future needs is incredibly difficult. Executing one successful project is lucky, but making it a repeatable process and strategic advantage? That's where the money is. With help from our most experienced project leads and software engineers, …

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds