Click here to Skip to main content
15,886,026 members
Articles / Desktop Programming / MFC
Article

CSingleInstance - Single Instance Apps

Rate me:
Please Sign up or sign in to vote.
4.98/5 (15 votes)
3 Mar 2000 270.9K   2.3K   69   43
An MFC class to implement single instance apps.

Introduction

Welcome to CSingleInstance, a freeware MFC class to make your app into a single instance. Limiting your app to single instance is more tricky in Win32 with the removal of the hPrevInstance parameter from WinMain and the introduction of separate address spaces.

There are numerous examples already out there of making your app single instance, but some such as the one I found on http://www.codeguru.com/ require knowledge of undocumented or heavy duty MFC.

Other methods such as using FindWindow or FindWindowEx are not 100% bullet proof due to the preemptive Win32 environment.

This class internally uses a memory mapped file (MMF) into which the handle of the main window of your application is stuffed. When a second instance of your app is run, it detects that the memory mapped file exists, gets the window handle of the first instance from the MMF and reactivates the old window.

The source zip file contains the CSingleInstance source code and a simple MFC app (without Doc/View) which demonstrates all the functionality of the class. For further details on how to use the class, have a look at the BOOL CMyApp::InitInstance() function and the included documentation.

Features
Usage
History
API Reference
Contacting the Author

Features

  • Very simple API, only 2 functions exposed.
  • Does not require any messing around with window styles and your mainfrm source code.
  • Much more robust implementation than other methods as already mentioned.
  • The classes are fully Unicode compliant and include Unicode built options in the workspace file.

Usage

To use the class in your code, simply include sinstance.cpp in your project and #include sinstance.h in your app's source file. Create your mainfrm window as normal but before you show it, simply include the following code:

CMyApp::InitInstance()
{
    CInstanceChecker instanceChecker;

    if (instanceChecker.PreviousInstanceRunning())
    {
      AfxMessageBox(_T("Previous version detected, will now restore it"), 
                                                                   MB_OK);
      instanceChecker.ActivatePreviousInstance();
      return FALSE;
    }

    ....

    // create main MDI Frame window
    CMainFrame* pMainFrame = new CMainFrame;
    m_pMainWnd = pMainFrame;

    if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
        return FALSE;

    // If this is the first instance of our App then
    // track it so any other instances can find it.
    if (!instanceChecker.PreviousInstanceRunning())
        instanceChecker.TrackFirstInstanceRunning();

    .....
}

That's all there is to it. Your application should now be single instance. For those interested in the nitty gritty of the code, have a look at sinstance.cpp.

History

  • V1.0 (29th July 1998)
    • Initial public release.
  • V1.01 (27th March 2000)
    • Now ships with a VC 5 workspace.
    • Fixed a potential handle leak where the file handle m_hPrevInstance was not being closed under certain circumstances.
    • The remaining changes were made by Neville Franks. Contact nevf@getsoft.com, http://www.getsoft.com/.
    • Changed #pragma error in instance header file to #pragma message. Former wouldn't compile under VC6
    • Replaced above #pragma with #include.
    • Added TrackFirstInstanceRunning(), MakeMMFFilename()
    • Split PreviousInstanceRunning() up into separate functions so we can call it without needing the MainFrame window.
    • Changed ActivatePreviousInstance() to return hWnd.
  • V1.02 (28th March 2000)
    • Minor update to the documentation.

API Reference

The API consists of the the two public member functions of the class CSingleInstance:

CSingleInstance::PreviousInstanceRunninging

BOOL CSingleInstance::PreviousInstanceRunning()

Return Value:

TRUE if a previous instance of this application is running, otherwise FALSE.

Remarks:

In response to TRUE being sent back the program, should call ActivatePreviousInstance() and abort prematurely from the current instance of the app.

CSingleInstance::ActivatePreviousInstance

BOOL CSingleInstance::ActivatePreviousInstance()

Remarks:

Activates the previous instance of the app as detected in a call to PreviousInstanceRunning().

Contacting the Author

PJ Naughter

Email: mailto:pjn@indigo..ie

Web: http://www.naughter.com/

29th July 1998

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
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRe: TrackFirstInstanceRunning() not in source code Pin
Leow11-Apr-00 4:40
Leow11-Apr-00 4:40 
GeneralDefinition of "single instance" not complete Pin
Daniel Lohmann8-Apr-00 9:10
Daniel Lohmann8-Apr-00 9:10 
GeneralRe: Definition of Pin
Neville Franks9-Apr-00 21:08
Neville Franks9-Apr-00 21:08 
GeneralRe: Definition of Single Instance Pin
Michael Tomlinson15-Mar-04 18:32
Michael Tomlinson15-Mar-04 18:32 
GeneralRe: Definition of Pin
Jim Howard1-Dec-00 8:22
Jim Howard1-Dec-00 8:22 
GeneralRe: Definition of "single instance" not complete Pin
pjnaughter3-Apr-03 23:35
pjnaughter3-Apr-03 23:35 
GeneralRe: Definition of "single instance" not complete Pin
pjnaughter16-Mar-04 10:45
pjnaughter16-Mar-04 10:45 
GeneralRe: Definition of "single instance" not complete Pin
Daniel Lohmann16-Mar-04 22:10
Daniel Lohmann16-Mar-04 22:10 
pjnaughter wrote:
This is not true (at least with the latest versions of my code), since you can specify the mutex name to use. That way the developer who uses the class can decide to specify a prefix of "Global\" or "Local\" so that they can decide which way they want to define the mutex. These extensions to the NT Name space with added to NT 4 Terminal Services edition and are a native part of Windows 2000

Right, but this leaves the problem still in the responsibility of the developer who uses your class. S/he still has to know about the subtle problems and to decide how to build a correct name.

Specifing the "Local\" or "Global\" prefix is, for instance, usually not enough. One point is, that it would fail on all (non-TS) systems prior to Win2k, because the backslash is an illegal character for kernel object names. Another point is, that it simply does not solve the issue. (Or lets say: It solves only part of the issue.)
If the programmer was responsible enough to use the "Local\" prefix (or no prefix at all, as "Local\" is the default inside a TS session) I can start the app in different TS sessions.
Fine. But the execution (via RunAs) of a second instance as another user in the *same* TS session is still prohibited. Does this really make sense? IMHO, this makes sense only in very few application scenarios.

As a developer: If I use a "ready-to-use" class for the instance check (especially if it is from PJ Naughter Wink | ;) ), I would expect it to deal with the critical cases on its own, instead of delegating me the job to create the "right" kernel object name for the intended instance-restriction.

You may want to take a look into my instance-check code at http://www.losoft.de/code/SingleInstance.zip. It is a more C-stylish solution, but shows how to create the different names. Please free to incorporate it into your class Big Grin | :-D

--

Daniel Lohmann

http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there Big Grin | :-D )
GeneralRe: Definition of "single instance" not complete Pin
pjnaughter17-Mar-04 3:31
pjnaughter17-Mar-04 3:31 
GeneralRe: Definition of "single instance" not complete Pin
pjnaughter9-May-04 8:36
pjnaughter9-May-04 8:36 
QuestionHow does this compare with just using a CMutex? Pin
James White6-Apr-00 7:24
James White6-Apr-00 7:24 
AnswerRe: How does this compare with just using a CMutex? Pin
Neville Franks9-Apr-00 20:59
Neville Franks9-Apr-00 20:59 
GeneralDoesn't seem to work with dialog based apps Pin
Newbie4-Apr-00 18:13
Newbie4-Apr-00 18:13 
GeneralRe: Doesn't seem to work with dialog based apps Pin
PJ Naughter5-Apr-00 11:49
PJ Naughter5-Apr-00 11:49 
GeneralRe: Doesn't seem to work with dialog based apps Pin
Newbie6-Apr-00 6:47
Newbie6-Apr-00 6:47 
GeneralRe: Doesn't seem to work with dialog based apps Pin
Stephan Walbaum11-Apr-00 9:14
sussStephan Walbaum11-Apr-00 9:14 
GeneralRe: Like this it does work with dialog based apps Pin
Stephan Walbaum19-Apr-00 6:40
sussStephan Walbaum19-Apr-00 6:40 
GeneralRe: Doesn't seem to work with dialog based apps Pin
pjnaughter17-May-00 10:39
pjnaughter17-May-00 10:39 

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.