Here's a mutex class based on that old Advisor code from 1998, and in
production from then until 2008! There's also an example on calling
it.

One thing to watch out for with all these approaches is fast-user
switching on Windows XP where more than one user can be logged on at
the same time.

--stuart

define class mutex as _line

        cFormCaption = ''
        hMutex = 0
        nMutexError = 0

        * credit to George Tasker for the code
        * published in FoxPro Advisor, november 1998
        procedure init

                lparameter lcFormCaption

                declare integer CreateMutex in Win32API;
                        string @lpMutexAttributes,;
                        string bInitialOwner,;
                        string @lpName

                declare integer GetLastError in Win32API

                local cOwner, cName

                * replace spaces with empty strings so the Mutex name is 
different
                * from the caption.
                cName = chrtran(lcFormCaption, space(1), '')
                * Simulate a BOOL type equaling TRUE.
                cOwner = chr(1)
                with this
                        .cFormCaption = lcFormCaption
                        .hMutex = CreateMutex(0, cOwner, @cName)
                        .nMutexError = GetLastError()
                endwith
                return
        endproc

        * note - I couldn't get George's DisplayInstance to work, so I've
used part of it and some other code..

        procedure DisplayInstance

                local cWindowName as string, nHWND as integer, nNextHWND as 
integer, ;
                        cBuffer as string, lDummy as Boolean, lIcon as Boolean

                cWindowName = this.cFormCaption

                * We don't want beautify to mess with ShowWindow (which is a VFP
keyword as well
                * as the DLL function name) - see
http://rickschummer.com/blog/2005/03/vfp-9-hidden-gem-beautify-directive.html

                * This is a directive instructing Beautify to ignore keywords 
(i.e.
ShowWindow)

*# beautify keyword_nochange

                declare integer SetForegroundWindow in win32api long lnhWnd
                declare integer GetWindowText in win32api integer, string, 
integer
                declare integer GetWindow in win32api integer,integer
                declare integer IsWindowVisible in win32api integer
                declare integer GetActiveWindow in win32api
                declare short IsIconic in win32API integer hwnd
                declare integer ShowWindow in win32API as WIN32_ShowWindow 
integer
hwnd, integer nCmdShow
                * End beautify directive.

*# beautify

                if len(cWindowName) < 1
                        return
                endif
                * get the window handle of this window
                nHWND = GetActiveWindow()
                * get the handle of the first window along
                nNextHWND = GetWindow(nHWND,0)

                * loop through each window to search the title
                do while nNextHWND <> 0
                        * if window is not this handle and not a child window
                        if (nNextHWND <> nHWND .and. GetWindow(nNextHWND,4) = 0)

                                cBuffer = space(64)
                                * get the window text
                                lDummy = GetWindowText(nNextHWND,@cBuffer,64)

                                * if this is the specified window.
                                if cWindowName $ cBuffer
                                        * Determine if the application
                                        * is minimized (an icon).
                                        lIcon = (IsIconic(nNextHWND) # 0)
                                        if lIcon
                                                * It's an icon, so restore it
                                                =WIN32_ShowWindow(nNextHWND, 9)
                                        endif
                                        =SetForegroundWindow(nNextHWND)
                                        exit
                                endif
                        endif
                        nNextHWND = GetWindow(nNextHWND, 2)
                enddo



        endproc


        procedure destroy

                declare integer WaitForSingleObject in Win32API;
                        integer hObject, integer dwTimeOut
                declare short ReleaseMutex in Win32API;
                        integer hMutex
                declare short CloseHandle in Win32API;
                        integer hObject
                        
                local nResult
                
                if this.hMutex # 0
                        nResult = WaitForSingleObject(this.hMutex, 50)
                        * 258 = STATUS_TIMEOUT
                        if nResult # 258
                                nResult = ReleaseMutex(this.hMutex)
                                * 1 equals Boolean TRUE
                                if nResult = 1
                                        nResult = CloseHandle(this.hMutex)
                                endif
                        endif
                endif
                
                return
        endproc

enddefine

This is a procedure designed to be called from an application class.
Note that the mutex handle returned must be stored so it can be
released when the app exits.

I can't remember why I implemented the property, must have been a reason though.

        procedure CreateAppMutex

                * Returns True if this is the only instance, otherwise attempts 
to display
                * the existing instance and returns False.
                local cName, cProperty, nHwnd, lOnlyInstance, nNextHWND, lIcon

                * Use appname for mutex name
                cName = chrtran(this.cAppName, space(1), "")

                * Use a specific property to identify this app
                cProperty = cName + "_APP_SINGLE_INSTANCE"

                this.hMutex = CreateMutex(0, chr(1), cName)

                if GetLastError() = 183 && ERROR_ALREADY_EXISTS

                        * get the window handle of this window
                        nHwnd = GetActiveWindow()
                        * get the handle of the first window along
                        nNextHWND = GetWindow(nHwnd, 0)

                        * loop through each window to look for the property:
                        do while nNextHWND <> 0
                                * if window is not this handle and not a child 
window
                                if (nNextHWND <> nHwnd and GetWindow(nNextHWND, 
4) = 0)

                                        if GetProp(nNextHWND, cProperty) = 1
                                                * Determine if the application
                                                * is minimized (an icon).
                                                lIcon = (IsIconic(nNextHWND) # 
0)
                                                if lIcon
                                                        * It is, so restore it:
                                                        
=WIN32_ShowWindow(nNextHWND, 9)
                                                endif
                                                * Attempt to set the window as 
frontmost
                                                =SetForegroundWindow(nNextHWND)
                                                exit
                                        endif
                                endif
                                nNextHWND = GetWindow(nNextHWND, 2)
                        enddo

                        * Release the window handle and mutex
                        CloseHandle(nHwnd)
                        * CloseHandle(hMutex)
                        this.ReleaseAppMutex()

                else
                        lOnlyInstance = .t.
                        SetProp(_vfp.hwnd, cProperty, 1)
                endif

                return lOnlyInstance

        endproc

procedure ReleaseAppMutex

                local nResult

                if this.hMutex # 0
                        nResult = WaitForSingleObject(this.hMutex, 50)
                        * 258 = STATUS_TIMEOUT
                        if nResult # 258
                                nResult = ReleaseMutex(this.hMutex)
                                * 1 equals Boolean TRUE
                                if nResult = 1
                                        nResult = CloseHandle(this.hMutex)
                                endif
                        endif
                endif

        endproc


On Wed, Jul 15, 2009 at 9:45 AM, Dave Crozier<[email protected]> wrote:
> Eurico,
> Or you could use scripting if it is allowed:
>
> *******
> * Start of Code
> *
> LOCAL llQuit
> *!* Check for instance(s) of Myapp running
> oManager = GETOBJECT([winmgmts:])
> cQuery = [select * from win32_process where name='myapp.exe']
> oResult = oManager.ExecQuery(cQuery)
>
> IF oResult.Count > 1
>  llQuit = .T.
> ENDI
> *!* Clean up
> oManager = .NULL.
> oResult = .NULL.
> RELEASE cQuery, oResult, oManager
>
> IF llQuit && Myapp.exe running twice
>  QUIT
> ENDIf
> *
> * End of Code
> *********
>
> Dave Crozier
>
> -----Original Message-----
> From: [email protected] [mailto:[email protected]] On Behalf
> Of Eurico Chagas Filho
> Sent: 14 July 2009 12:12
> To: 'ProFox Email List'
> Subject: How to avoid two instances
>
>
> I came across a code written by Ramani to avoid two instances of an
> application in the same desktop.
> It uses extensively the DDE functions, is there anything I should be aware
> of ?
>
> TIA, E.
>
>
>
[excessive quoting removed by server]

_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/profox
OT-free version of this list: http://leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: 
http://leafe.com/archives/byMID/profox/[email protected]
** All postings, unless explicitly stated otherwise, are the opinions of the 
author, and do not constitute legal or medical advice. This statement is added 
to the messages for those lawyers who are too stupid to see the obvious.

Reply via email to