Members

Technology Zones

IBM Learning Center

Articles

Hosted By

MaximumASP

Info

Rated
Read 28,512 times

Contents

Downloads

Related Categories

Avoiding Multiple Instances of an Application - The source code

flounder

The source code

exclusion.h

#define UNIQUE_TO_SYSTEM  0
#define UNIQUE_TO_DESKTOP 1
#define UNIQUE_TO_SESSION 2
#define UNIQUE_TO_TRUSTEE 3
CString createExclusionName(LPCTSTR GUID, UINT kind = UNIQUE_TO_SYSTEM);

exclusion.cpp

#include "stdafx.h"
#include "exclusion.h"
/****************************************************************************
*                             createExclusionName
* Inputs:
*       LPCTSTR GUID: The GUID for the exclusion
*       UINT kind: Kind of exclusion
*               UNIQUE_TO_SYSTEM
*               UNIQUE_TO_DESKTOP
*               UNIQUE_TO_SESSION
*               UNIQUE_TO_TRUSTEE
* Result: CString
*       A name to use for the exclusion mutex
* Effect: 
*       Creates the exclusion mutex name
* Notes:
*       The GUID is created by a declaration such as
*               #define UNIQUE _T("MyAppName-{44E678F7-DA79-11d3-9FE9-006067718D04}")
****************************************************************************/
CString createExclusionName(LPCTSTR GUID, UINT kind)
   {
    switch(kind)
       { /* kind */
        case UNIQUE_TO_SYSTEM:
           return CString(GUID);

        case UNIQUE_TO_DESKTOP:
           { /* desktop */
            CString s = GUID;
            DWORD len;
            HDESK desktop = GetThreadDesktop(GetCurrentThreadId());
            BOOL result = GetUserObjectInformation(desktop, UOI_NAME, NULL, 0, &len);
            DWORD err = ::GetLastError();
            if(!result && err == ERROR_INSUFFICIENT_BUFFER)
               { /* NT/2000 */
                LPBYTE data = new BYTE[len];
                result = GetUserObjectInformation(desktop, UOI_NAME, data, len, &len);
                s += _T("-");
                s += (LPCTSTR)data;
                delete [ ] data;
               } /* NT/2000 */
            else
               { /* Win9x */
                s += _T("-Win9x");
               } /* Win9x */
            return s;
           } /* desktop */

        case UNIQUE_TO_SESSION:
           { /* session */
            CString s = GUID;
            HANDLE token;
            DWORD len;
            BOOL result = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
            if(result)
               { /* NT */
                GetTokenInformation(token, TokenStatistics, NULL, 0, &len);
                LPBYTE data = new BYTE[len];
                GetTokenInformation(token, TokenStatistics, data, len, &len);
                LUID uid = ((PTOKEN_STATISTICS)data)->AuthenticationId;
                delete [ ] data;
                CString t;
                t.Format(_T("-%08x%08x"), uid.HighPart, uid.LowPart);
                return s + t;
               } /* NT */
            else
               { /* 16-bit OS */
                return s;
               } /* 16-bit OS */
           } /* session */

        case UNIQUE_TO_TRUSTEE:
           { /* trustee */
            CString s = GUID;
#define NAMELENGTH 64
            TCHAR userName[NAMELENGTH];
            DWORD userNameLength = NAMELENGTH;
            TCHAR domainName[NAMELENGTH];
            DWORD domainNameLength = NAMELENGTH;

            if(GetUserName(userName, &userNameLength))
               { /* get network name */
                // The NetApi calls are very time consuming
                // This technique gets the domain name via an
                // environment variable
                domainNameLength = ExpandEnvironmentStrings(_T("%USERDOMAIN%"),
                                                            domainName,
                                                            NAMELENGTH);
                CString t;
                t.Format(_T("-%s-%s"), domainName, userName);
                s += t;
               } /* get network name */
            return s;
           } /* trustee */
        default:
            ASSERT(FALSE);
            break;
       } /* kind */
    return CString(GUID);
   } // createExclusionName

Back in the original example, replace the string which I hardwired into the ::CreateMutex call with a call on createExclusionName with the desired specification to get a correctly-formatted unique name to use for the Mutex.

Comments

  • Possible problem

    Posted by harpreetBamrah on 13 Jul 2005

    I am making a single instance appilcation and have followed all your suggestions . And i am really thankful to you for writing such an informative article.But i have a problem. It is my requirement th...

  • Great work

    Posted by vivek.kumbhojkar on 17 May 2004

    The article is realy good Even other tips and artcles by Joseph M. Newcomer are excellent for those who want to master vc++

  • cookbook version, single instance

    Posted by malyj on 01 Dec 2003

    Brilliant article!! Here it is again, boiled down to cookbook code for your MyApp.cpp file.
    Many thanks to Joseph Newcomer & Daniel Lohmann. // Mark Malyj

    //Avoiding Multiple Instances of an Appli...

  • Very Useful

    Posted by Randalism on 19 Apr 2002

    I found this information useful for an implementation that did not involve "Avoiding Multiple Instances of an Application," but did involve use of an EnumWindows() callback loop which was freezing up ...