Click here to Skip to main content
15,888,527 members
Articles / Programming Languages / C++
Article

Single Instance Application - The simple solution

Rate me:
Please Sign up or sign in to vote.
1.75/5 (6 votes)
21 Nov 20023 min read 99.6K   1.6K   13   14
The solution for the single instance application issue with command line arguments.

Introduction

Here is one more solution to solve the one instance application issue. The main distinguishing feature of this implementation is simplicity. It's not bound to MFC and can be used in pure Win32 application, no matter GUI or console. But MFC version is also present. There are two demo projects (MFC and Win32) to demonstrate how it works. Try to start several instances to see what happens.

How does this work

The first instance of application creates file mapping, registers window message and save its thread ID in the file mapping. The second instance opens the file mapping, copies its command line to the file mapping and posts registered window message to the first instance thread. The posted message notifies the first instance that command line of the second instance is available. So, it uses one file mapping and one registered windows message. Implementation is very lightweight - you don't have to pay much for such a common task.

Background

I wrote this in response to Single Instance Application by Justin Hallet . I found his implementation too complicated (one mutex, one thread, one file mapping, two events - whoa, this is overhead!). Indeed, because such a code keeps the computer running needlessly, it also needlessly increases the entropy of the universe, thereby hastening said heat death. In short, such a code is quite environmentally unfriendly and should be considered a threat to our species :). (Copyright © 2002 Herb Sutter )

Implementation presented here is made as simple as possible.

Using the code with MFC

It's very simple to use it with MFC.

  1. Derive your application class from CSingleInstanceApp instead of CWinApp. Do not forget to include SingleInstanceApp.h in your application class header.
  2. class CMyApp : public /*CWinApp*/ CSingleInstanceApp
    {
        // ...
    };
  3. Replace all references to CWinApp with CSingleInstanceApp in your CSingleInstanceApp-derived class.
  4. Add the code to the CMyApp constructor:
  5. CMyApp::CMyApp() :
    CSingleInstanceApp(TEXT("{49E4CD26-9489-4474-91B0-2A30F6CA3097}"))

    Please note, that argument to CSingleInstanceApp constructor must be the pointer to the system unique string (it is used to name the file mapping and to register the window message). Replace it with newly generated GUID.

  6. Add the check to InitInstance method of your application class.
  7. BOOL CMyApp::InitInstance()
    {
        if (!AmITheFirst())
            return false;
        // ...
  8. Optional. Override the CSingleInstanceApp::OnSecondInstance method to get notified when the second instance is being tried to start. You can use here the CSingleInstanceApp::GetSecondInstanceCmdLine() method to get the second instance command line.

Using the code without MFC

It's also very simple.

  1. Define UINT variable and SingleInstanceApp instance like this:
  2. UINT uSecondInstanceMessage;
    SingleInstanceApp single(TEXT(
                "{B0C9E56F-687A-4c1f-9862-2F4D0F748827}"), 
                uSecondInstanceMessage);

    These two must be accessible from scope of the application message loop. The easiest way to do this is to define it at the global scope.

  3. Having single defined at the global scope add the check at your
    WinMain
    function:
  4. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
            LPSTR lpCmdLine, int nCmdShow)
    {
        if (!single.AmITheFirst())
            return false;
        // ...
  5. Optional. Registered message posted by
    PostThreadMessage()
    function can't be dispatched to a window procedure. So, add the code to your application message loop to get notified when the second instance is being tried to start. You can use here the SingleInstanceApp::GetSecondInstanceCmdLine() method to get the second instance command line:
  6. while (GetMessage(&msg, NULL, 0, 0))
    {
        if (uSecondInstanceMessage == msg.message)
        {
            // add your code here
            continue;
        }
        // ...

That's all folks :)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionUse named mutex ok? Pin
SeanNick26-Jul-06 3:41
SeanNick26-Jul-06 3:41 
AnswerRe: Use named mutex ok? Pin
MaximE26-Jul-06 23:03
MaximE26-Jul-06 23:03 
AnswerRe: Use named mutex ok? Pin
Member 239604227-Jun-08 6:31
Member 239604227-Jun-08 6:31 
QuestionWhat if I use Event for this purpose Pin
opsoft-op5-Dec-05 23:56
opsoft-op5-Dec-05 23:56 
Generalpointless Pin
Mach0052-Apr-04 6:26
Mach0052-Apr-04 6:26 
GeneralNice Example - but Pin
Justin Hallet25-Nov-02 4:23
Justin Hallet25-Nov-02 4:23 
GeneralRe: Nice Example - but Pin
MaximE25-Nov-02 9:31
MaximE25-Nov-02 9:31 
Generalbut you do need synchronization... Pin
Paolo Messina23-Nov-02 4:00
professionalPaolo Messina23-Nov-02 4:00 
GeneralRe: but you do need synchronization... Pin
MaximE23-Nov-02 8:31
MaximE23-Nov-02 8:31 
GeneralRe: but you do need synchronization... Pin
Ernest Laurentin23-Nov-02 14:59
Ernest Laurentin23-Nov-02 14:59 
GeneralRe: but you do need synchronization... Pin
Paolo Messina24-Nov-02 2:41
professionalPaolo Messina24-Nov-02 2:41 
GeneralRe: but you do need synchronization... Pin
MaximE24-Nov-02 19:58
MaximE24-Nov-02 19:58 
In the case of pressing Enter while having multiple files selected assotiated with application I must ensure that the first instance will get all the file names. All-or-nothing. To do so, all the other instances must communicate with the first instance to pass its command lines. This communication must be serialized and the first instance can't ignore it. Adding a mutex does not solve this problem.

This will not be a simple solution.

I'll think about this and check out does race condition can really take place.
GeneralRe: but you do need synchronization... Pin
Paolo Messina25-Nov-02 1:16
professionalPaolo Messina25-Nov-02 1:16 
GeneralRe: but you do need synchronization... Pin
MaximE25-Nov-02 9:31
MaximE25-Nov-02 9:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.