Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

There are already two article about "Single instance", both of them use a "mutex". All the code worked perfectly, and it is enough for most case. But if you want to do something more as following, you may choose this one which use "DDE" ( dynamic data exchange ).

First: If the first instance want to know the second instance is running. In most case, the first instance should be actived if the second one launch. In the article use "mutex", the second instance find the first one by special window class name, then actived the first one. But the first instance do NOT know another instance has been run, and it have no choice but been actived by second instance.

Second: If the second instance should send some data to first one. Understand it this way: "Winword" is running, then you double click another .doc file in "Explore". Second instance of "Winword" should be terminated, but before it end, it must send the filename to the first instance.

Yes, "Winword" use DDE to ensure only one instance can be run. Do a test by changed the CppServerName to "Winword" and changed CppTopicName to "System" ( the two are both const in program ). Run it, then word will active my program if you click a .doc file again. ( you should know, winword can be run with muti-instance by click the program icon. It only detect instance when you click a .doc file )

Now, if you find this useful, and try to use DDE, let's step by step to finish.

First: As you see, we use DDE, so you should add ddeml.h into your project, and I recommend add it in your "Stdafx.h", instead of add this line here and there. add the following line into your "Stdafx.h"

#include "ddeml.h" 

Second: handle the "InitInstance" and "ExitInstance" of you class base on CWinApp, if you have not do it yet. In the sample code the class name is "CTestApp", it is declare in "Test.h", and define in "Test.Cpp". you may have different name in different project.Third: Add the following into your CTestApp class, in "test.h"

        bool isRun;
        DWORD idInst;
        HSZ hszCppServer, hszCppTopic;
        HCONV hconvCppServer;
        DWORD dderesult; 
    and add the following in "test.h" but out of any class, for it is CALLBACK 

Fourth: define your DDE server name and topic name Add the following into your "test.cpp"

    #define CppServerName "TEST_SERVER"
    #define CppTopicName "TEST_TOPIC"

different project should have different server name

Fifth: add the following just after the #define

    CTestApp* p_OneApp; 

Sixth: add the following into your consturction

        p_OneApp = this;
        isRun = false;

Seventh: Add the following at the begining of your InitInstance

    BOOL CTestApp::InitInstance()
        if (DdeInitialize(&idInst, (PFNCALLBACK)DdeCallback, 0, 0)) return false; 
        hszCppServer = DdeCreateStringHandle ( idInst, CppServerName, CP_WINANSI );
        hszCppTopic = DdeCreateStringHandle ( idInst, CppTopicName, CP_WINANSI ); 
        // try to find the first instance
        hconvCppServer = DdeConnect ( idInst, hszCppServer, hszCppTopic, NULL );
        if ( hconvCppServer )
            isRun = true;
//    have connection, this is the second instance, you can send data to first instance  
//            DdeClientTransaction((unsigned char*)data, strlen(data)+1, 
//              hconvCppServer, 0, CF_TEXT, XTYP_EXECUTE, 0, &dderesult );   
            return false;
        DdeNameService ( idInst, hszCppServer, 0, DNS_REGISTER );

Eighth: Add the following into your ExitInstance

    int CTestApp::ExitInstance() 
        DdeFreeStringHandle ( idInst, hszCppServer );
        DdeFreeStringHandle ( idInst, hszCppTopic ); 
        // only unregister the DDE server for first instance
        if ( !isRun )
            if ( !DdeNameService ( idInst, hszCppServer, 0, DNS_UNREGISTER ) )
                ::MessageBox ( 0, "Error", "in ServiceUnRegister", MB_OK );

Nineth: Add the following into your "Test.Cpp"

    HDDEDATA CALLBACK DdeCallback(WORD wType, WORD wFmt, HCONV hConv, HSZ hszTopic,
        HSZ hszItem, HDDEDATA hData, DWORD lData1, DWORD lData2)
        return ( p_OneApp -> AppDdeCallback( wType, wFmt, hConv, hszTopic, hszItem, 
            hData, lData1, lData2 ) );

    HDDEDATA CTestApp::AppDdeCallback(WORD wType, WORD wFmt, HCONV hConv, HSZ hszTopic,
        HSZ hszItem, HDDEDATA hData, DWORD lData1, DWORD lData2)
        int icount;
        char* buffers;
        CWnd* p_Wnd; 
        switch ( wType )
            case XTYP_CONNECT:
                icount = DdeQueryString ( idInst, hszTopic, NULL, 0, CP_WINANSI );
                buffers = (char*)malloc ( icount+1 );
                DdeQueryString ( idInst, hszTopic, buffers, icount+1, CP_WINANSI );
                if ( !strcmp ( buffers, CppTopicName ) )
                    p_Wnd = AfxGetMainWnd();
                    p_Wnd -> ShowWindow(SW_RESTORE);
                    p_Wnd -> BringWindowToTop( );
                    p_Wnd -> SetForegroundWindow( ); 
//    add any code for the first instance have found the second one is launch
                    ret = (HDDEDATA) DDE_FACK;
                free ( buffers );
                return ret; 
            case XTYP_EXECUTE:
//    if the second instance send data, the first one received here.  
//                icount = DdeGetData ( hData, NULL, 0, 0 );
//                buffers = (char*)malloc ( icount+1 );
//                DdeGetData ( hData, (unsigned char*)buffers, icount, 0 );
//                free ( buffers );
                return ret;
            default: return ret;

When second instance launch, it calls DdeConnect(), then the DDEML call the CALLBACK function for first instance with XTYP_CONNECT type. The first instance can determine do what by itself. If connection, second instance can send data by DdeClientTransaction() with XTYP_EXECUTE type. and the first one can received it at the CALLBACK function with XTYP_EXECUTE type.


  • Great Article!!

    Posted by sabapathy on 03/23/2006 11:20am

    Hi This is Great Article!! I got enabled double click open of my project files, in vc .net 2003 Thanks & Regards, sabapathy sabapathy_80@yahoo.com

  • Why make it hard on yourself...

    Posted by Legacy on 03/25/2002 08:00am

    Originally posted by: Mouse

    to detect if another instance of your app is running all you have to do is:

    1) on the INIT function of your app create a mutex as so:

    ::CreateMutex(NULL, FALSE, "UniqueMutexHandleForYourApp");

    2) call ::GetLastError() and see if the mutex has allready been created (obviously it allready exists since there is allready one instance of your app running that allready created it successfully)

    if(::GetLastError() == ERROR_ALREADY_EXISTS){
    // dont load this instance.
    return FALSE;

    When the instance that owns the Mutex closes, it will automatically release the mutex and close the handle to it, so you dont ever have to worry about it again.

  • Excellent

    Posted by Legacy on 02/12/2002 08:00am

    Originally posted by: Aries

    Thanks Raymon, saved my nutsack. Great code, easy to add.

  • Problems with DdeConnect

    Posted by Legacy on 10/25/2000 07:00am

    Originally posted by: Jose Luis Briones

    Im trying to make an application who has to establice conversation using DDE with other application. My problem come in the next line:
    hconv = DdeConnect(idInst,hservname,htopicname,NULL);
    All the arguments in my function are well initializated, but my program breaks: why?

  • Sometimes Hangs Program....

    Posted by Legacy on 08/17/2000 07:00am

    Originally posted by: Brent

    This is a great piece of code and most of the time works perfectly. However it seems that on very rare occasions, I will get stuck in the function:

    hconvCppServer = DdeConnect ( idInst, hszCppServer, hszCppTopic, NULL );

    for up to a minute. Do you know if there is anything I can do to avoid this?


  • Another method that works well, easy to use.

    Posted by Legacy on 05/24/2000 07:00am

    Originally posted by: Todd Osborne

    The free VWCL class library (www.vwcl.org) has a class called VSingleInstanceAppRestriction. It uses Win32 named mutexes to achieve similar results. One nice thing about it is that it can communicate with the original instance of a running application using simpler WM_COPYDATA messages. That way the 1st instance can receive information about the second instance, such as command line parameters or passed in file names. It can then act on it.


  • Bravo!

    Posted by Legacy on 07/01/1999 07:00am

    Originally posted by: Chuck Messenger

    Great stuff -- thanks for sharing it! Having tried various methods in the past, and having studied the other methods presented on the CodeGuru site, I was very pleased to learn about the DDE method you describe. It is easily the most elegant solution, and works as well with a dialog-based app as with a "regular" app.

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date