TIP: Dialog-Based, Single-Instance Applications

Introduction

There are lots of articles on CodeGuru about limiting your program to a single instance. In this article, I want to show how easily it can be done by simply modifying the dialog template and adding few lines of code in InitInstance(). Although I use MFC for this sample, you can use the same technique for ATL/WTL and generic Win32 applications.

Implementation

  • Create an MFC dialog-based project.
  • Open the Resource Script file (.rc), find your main dialog template, and add the following lines:
    CLASS "SINGLE_INSTANCE_APP"
    
    IDD_SINGLEINSTANCE_DIALOG DIALOGEX 0, 0, 320, 200
       STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS |
             WS_POPUP | WS_VISIBLE |
             WS_CAPTION | WS_SYSMENU
       EXSTYLE WS_EX_APPWINDOW
       CLASS "SINGLE_INSTANCE_APP"
       CAPTION "Single Instance Application"
       ...
    

    This will instruct Windows to use your own windows class "SINGLE_INSTANCE_APP" instead of a standard dialog class.

  • Now, you have to register the "SINGLE_INSTANCE_APP" windows class. The best place for this is InitInstance().
  •    WNDCLASS wc = {0};
       wc.style = CS_BYTEALIGNWINDOW|CS_SAVEBITS|CS_DBLCLKS;
       wc.lpfnWndProc = DefDlgProc;
       wc.cbWndExtra = DLGWINDOWEXTRA;
       wc.hInstance = m_hInstance;
       wc.hIcon = LoadIcon(IDR_MAINFRAME);
       wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
       wc.hbrBackground =
          CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
       wc.lpszClassName = _T("SINGLE_INSTANCE_APP");
       ATOM cls = RegisterClass(&wc);
    
  • After this, you can find your main dialog by its class name.
  • CWnd* pWnd =
       CWnd::FindWindow(_T("SINGLE_INSTANCE_APP"), NULL);
    if (pWnd)
    {
       pWnd->ShowWindow(SW_SHOW);
       pWnd->SetForegroundWindow();
       return FALSE;
    }
    


About the Author

Khachatur Petrosyan

View http headers, analyze http traffic with HTTP Debugger

Downloads

Comments

  • Bad approach!

    Posted by Partizan on 03/30/2006 03:31pm

    "There are lots of articles on CodeGuru about limiting your program to a single instance" There are also lots of articles on the Net describing why this approach is quite bad. Please read this article by Joseph Newcomer: http://www.codeproject.com/cpp/avoidmultinstance.asp

    • Re: If it depends, then state clearly all limitations and uses

      Posted by pkhach on 06/23/2006 03:26pm

      I am writing programs on C++ for already 12 years and have an idea about these problems. As I write before I am using this technique in my programs since 2000 year. They work on Win95-WinXP computers and I NEVER have any problem related to this technique. Of course each developer should decide whether it is acceptable for his particular program on not, as well as to decide what to use: FindWindow, CreateMutex, WinNT Service or even EnumProcesses. I repeat everything depends on a particular program. Do you really believe that using the kernel level objects (named mutex, semaphore, etc) is the ideal solution for all cases? Or do you really think that a chance that a developer used the "SINGLE_MUTEX_APP" name for his mutex is lower then "SINGLE_INSTANCE_APP" for a window class name? And of course FindWindow is unique only on user level not on system. Good luck. KP

      Reply
    • If it depends, then state clearly all limitations and uses

      Posted by Partizan on 06/22/2006 12:37pm

      In the above 3 points that you listed there's a chance of it failing. The fact that it works on YOUR machine, does not mean that it will always work on a CUSTOMER machine. You'll be surprised how often it happens when something works on your machine and you 100% sure it will work everywhere, but you give it to your colleage or worse yet ship it to customer and find out that it fails to work properly. For your approach to work, two of the following conditions must be met: 1. Target machine is not Windows XP or Windows XP with fast user switching disabled. 2. Some other developer does not register class for his dialog app as "SINGLE_INSTANCE_APP". Fast user switching is enabled by default on XP and FindWindow will return NULL if another instance is being run by another user. See this KB for more info: http://support.microsoft.com/default.aspx?scid=kb;en-us;310153 You should really clarify in your article limitations and uses of your approach. There is also more than one definition of what exactly is considered "single instance". Is it one app per machine, per user account, per desktop? It's all laid out clearly in the link I gave in my first comment: http://www.codeproject.com/cpp/avoidmultinstance.asp

      Reply
    • It depends

      Posted by pkhach on 06/21/2006 12:59pm

      Damir, 1. How about finding the running instance of program in order to close it during un-installation (by sending a special command to it)? 2. How about sending/retrieving some data from running instance via WM_COPY_DATA messages? 3. How about if your program starts automatically with Windows ("...\CurrentVersion\Run' registry key) and we just need to make sure that there is only once instance of program? 4. There are hundreds of other situations where this method can do a good job. I am using this technique in my programs where appropriate and I am quite happy with it. If you donb

      Reply
    • Re: Bad approach!

      Posted by Partizan on 06/21/2006 10:11am

      I also like simple solutions. But if you are OK with 1% failure rate, than you might as well not bother restricting anything at all and allow multiple instances. This 1% will happen on some customer's machine, and he/she definately will not be happy if one instance will start overwriting data of another (or do whatever you trying to prevent it from doing with a single instance).

      Reply
    • Re: Bad approach!

      Posted by pkhach on 03/31/2006 12:05am

      I already read this and many similar articles. I prefer simple solutions for simple tasks. This code works for 99% cases, just don't put any extra initialization code between FindWIndow check and CDialog::Create (or CDialog::DoModal). Also this technique give you ability to manipulate with handle existing window (you can restore/show/hide it). Regards, Khachatur

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

Top White Papers and Webcasts

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

  • New IT trends to support worker mobility — such as VDI and BYOD — are quickly gaining interest and adoption. But just as with any new trend, there are concerns and pitfalls to avoid.  Download this paper to learn the most important considerations to keep in mind for your VDI project.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds